Я хочу иметь индикатор выполнения XHTML + CSS с контрастными цветами между заполненными и пустыми областями фона.

У меня проблема с цветом текста. Поскольку заполненный и пустой фон слишком контрастны (это требование), чтобы текст оставался читабельным, он должен быть двухцветным, чтобы контрастировать с обоими. Изображение должно объяснить это лучше, чем слова:

Индикатор выполнения с темно-синей заливкой и белым пустым фоном http://drdaeman.pp.ru/tmp/20090703/progress-bar-text-example.png Пример проблемы http://drdaeman.pp.ru/tmp/20090703/progress-bar-text-problem.png

Моя текущая реализация индикатора выполнения тривиальна, но, как показывает пример выше, в некоторых случаях текст может быть трудно читать, и это именно та проблема, которую я хочу решить.

Моя текущая (упрощенная) попытка реализации (неудачная, потому что overflow: hidden не работает без позиционирования div.progress, которое я не могу позиционировать из-за внутреннего span width):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
  <title>Progress bar test</title>
  <style type="text/css">
    div.progress_bar {
        border: 1px #ccc solid; position: relative;
        text-align: center; height: 32px;
    }
    div.progress_bar .progress {
        height: 32px;
        overflow: hidden; /* This does NOT work! */
    }
    div.progress_bar .progress div {
        position: absolute; width: 100%; height: 32px;
        z-index: 30; overflow: hidden;
        background-color: #44a;
    }
    div.progress_bar span {
        position: absolute; top: 0; left: 0; width: 100%;
        z-index: 20;
        color: #000;
    }
    div.progress_bar .progress span {
        position: absolute; top: 0; left: 0; width: 100%;
        z-index: 40;
        color: #eee;
    }
  </style>
</head>
<body>
  <!-- Can be of any (unknown) width. Think of "width: auto".
       The 400px value is just to keep it small on a big monitor.
       DON'T rely on it! -->
  <div id="container" style="width: 400px;">
    <div class="progress_bar">
      <!-- div.progress is a dark filled area container -->
      <div class="progress" style="width: 51%;">
        <!-- Actually dark filled area -->
        <div style="width: 51%;"></div>
        <!-- Text (white).
             Does not clip, even with overflow: hidden on parent! -->
        <span>This is a test</span>
      </div>
      <!-- Text (black) -->
      <span>This is a test</span>
    </div>
  </div>
</body>
</html>

Живая версия вышеуказанного: http://drdaeman.pp.ru/tmp/20090703/test2 .html
Предыдущая попытка: http://drdaeman.pp.ru/tmp/20090703/test.html < / а>

Изображения представляют собой прототипы, отредактированные GIMP, а не то, что отображает этот код.

Добавить: Всем спасибо, особенно Meep3D, Nosredna и Lachlan! Однако у меня все еще есть проблема - в моем случае индикатор выполнения не должен иметь фиксированной ширины и занимать все доступное по горизонтали пространство (допустимы width: auto; или width: 100%). Но без правила width: 400px код Лахлана нарушается. И я по-прежнему хотел бы избегать использования JavaScript, если это возможно.

7
drdaeman 4 Июл 2009 в 00:17

6 ответов

Лучший ответ

Согласно предложению Meep3D, возьмите 2 копии текста.

Оберните каждый блок div той же ширины, что и контейнер. «Верхний» блок обёрнут другим блоком, который закрепляется в желаемом процентном соотношении.

Обновление: убрана фиксированная ширина.
Размер «верхнего» блока равен проценту, обратному его оболочке.

<html>
<head>
  <style type="text/css">
    #container {
        position: relative;
        border: 1px solid;
        text-align: center;
        width: 400px;
        height: 32px;
    }
    .black-on-white {
        height: 32px;
        color: #000;
    }
    .white-on-black {
        height: 32px;
        color: #fff;
        background-color: #44a;
    }
    .wrapper {
        width: 53%;
        overflow: hidden;
        position: absolute;
        top: 0; left: 0;
    }
    .black-on-white {
        width: 100%;
    }
    .white-on-black {
        width: 188.7%;
    }
  </style>
</head>
<body>
  <div id="container">
    <div class="wrapper">
        <div class="white-on-black">
             <span>This is a test</span>
        </div>
    </div>
    <div class="black-on-white">
        <span>This is a test</span>
    </div>
  </div>
</body>
</html>
8
Lachlan Roche 4 Июл 2009 в 13:18

А как насчет того, чтобы поместить вторую копию текста индикатора выполнения внутри div и установить скрытие переполнения div, чтобы оно отображалось вместе с ним?

-

Обновление: я также не эксперт по javascript, но я уверен, что вы можете узнать ширину объекта, а затем установить смещение на основе этого, если ширина является гибкой, как вы говорите.

8
Meep3D 4 Июл 2009 в 11:08

Ты мог бы:

  • Найдите серый, который подходит
  • Используйте JavaScript для динамического изменения цвета с белого на черный, в зависимости от того, где он находится.
  • Сделайте средний цвет фонового градиента ближе к белому и всегда используйте темный текст.
  • Поместите прогресс outisde в поле:
[#########              ] 50 % 
1
Lucas Jones 3 Июл 2009 в 20:19

Вы можете использовать текстовую тень для своего «процентного» текста. Единственным недостатком этого является то, что он будет работать только в последних версиях браузеров. Только Firefox 3.5, Safari (все версии) и Chrome 2+ поддерживают его.

Вот демонстрация использования text-shadow таким образом, чтобы ваш прогресс был удобочитаемым.
http://www.w3.org/Style/Examples/007/ text-shadow # белый

Если вы хотите использовать больше JavaScript, вы можете попробовать этот плагин jQuery:

http://kilianvalkhof.com/2008/javascript/text-shadow-in-ie-with-jquery/

В статье говорится, что он работает только в IE, однако он работает в Chrome 3 (что я использую), Firefox 3.5, Internet Explorer и Safari. Он может работать в старых браузерах, но я его не тестировал.

1
Dan Herbert 3 Июл 2009 в 20:33

Вам нужны 2 значения, оформленные по-разному. И фиксированная ширина

let counter = 0

const increment = () => {
  counter++
}

let interval = setInterval(() => {
  increment();
  document.querySelectorAll('.value').forEach(node => {
    node.textContent = `${counter}`  
  });
  document.querySelector('.progress-bar').style.width = `${counter}%`
  if (counter >= 100) clearInterval(interval);
}, 50)
.progress-wrapper{
  margin: 20px auto;
  width: 400px; 
  height: 20px;
  background-image: linear-gradient(45deg, #ccc 25%, transparent 25%, transparent 50%, #ccc 50%, #ccc 75%, transparent 75%, transparent);
  animation: progress-bar-stripes 2s linear infinite;
  background-size: 40px 40px;
  position: relative;
  border-radius: 5px;
  overflow: hidden;
 
}
.progress-bar{
  z-index: 3;
  overflow: hidden;
  position: absolute;
  height: 20px;
  background-color: #8178d9; 
  text-align: center;
  transition: width 0.5s ease;
}
.progress-value-1, .progress-value-2{
  margin: 0;
  position: absolute;
  width: 400px; 
  color: #8178d9;
  text-align: center;
  z-index: 2;
  font-weight: bold;
}
.progress-value-2{
  color: #fff;
  z-index: 1;
}
@keyframes progress-bar-stripes {
  from {
    background-position: 40px 0;
  }
  to {
    background-position: 0 0;
  }
}
<div class="container">
  <div class="progress-wrapper">
    <div class="progress-bar">
      <p class="progress-value-2">
        <span class="value"></span>%
      </p>
    </div>
    <p class="progress-value-1">
      <span class="value"></span>%
    </p>
  </div>
</div>

https://codepen.io/kosachevlad/pen/dypEjBa

1
Vlad Kosachev 25 Янв 2021 в 09:36

Meep3D дает правильный ответ. Две версии коробки. Выявить n% верхнего.

Больше опций:

  • Поместите полупрозрачный прямоугольник под числом, который либо затемняет область для белого числа, либо осветляет область для черного числа.
  • Используйте красный и белый в качестве фона и черный номер. (Проблема здесь в том, что красный цвет связан с ошибкой, поэтому вы можете играть с другими комбинациями трех цветов, которые все сильно контрастируют друг с другом.)
1
Nosredna 3 Июл 2009 в 20:41