Я хотел бы иметь индикацию прогресса, используя эмулированную анимацию границы в div. Этот div является элементом flexbox с относительной позицией. Я добавляю псевдоэлемент для анимации нижней части границы.
CSS
.test {
display: flex;
box-sizing: border-box;
width: 384px;
border: 1px solid;
height: 48px;
position: relative;
}
.test:before {
content: '';
position: absolute;
bottom: 0;
left: 0;
// width: 100%;
width: -webkit-fill-available;
height: 2px;
background: red;
animation: running-progress 2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
@keyframes running-progress {
0% { margin-left: 0px; margin-right: 100%; }
50% { margin-left: 25%; margin-right: 0%; }
100% { margin-left: 100%; margin-right: 0; } }
Вот кодовый ящик с проблемой:
https://codesandbox.io/s/yopwy5klz
Вопрос
Как ограничить ширину в этом примере, чтобы псевдоэлемент не превышал заданную ширину поля?
К вашему сведению, если я добавлю width: -webkit-fill-available;, он будет работать нормально, но я не думаю, что это правильное решение.
Вот "рабочая" версия https://codesandbox.io/s/wyp8q26qvk






Вместо анимации полей анимируйте свойства left и right и удалите width: 100% псевдоэлемента:
.test {
position: relative;
box-sizing: border-box;
width: 384px;
height: 48px;
border: 1px solid;
}
.test::before {
position: absolute;
bottom: 0;
height: 2px;
background: red;
animation: running-progress 2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
content: '';
}
@keyframes running-progress {
0% {
left: 0px;
right: 100%;
}
50% {
left: 25%;
right: 0%;
}
100% {
left: 100%;
right: 0;
}
}<div class = "test"></div>Вы также можете сделать это с одним элементом и linear-gradient:
.box {
position: relative;
box-sizing: border-box;
width: 384px;
height: 48px;
border: 1px solid;
background:
linear-gradient(red,red) bottom/100% 2px no-repeat;
animation: running-progress 2s cubic-bezier(0.4, 0, 0.2, 1) infinite
}
@keyframes running-progress {
0% {
background-position: bottom left;
background-size:0% 2px;
}
50% {
background-position: bottom right;
background-size:70% 2px;
}
100% {
background-position: bottom right;
background-size:0% 2px;
}
}<div class = "box"></div>Поскольку transform использует графический процессор, вы хотите использовать его для анимации, поскольку он будет иметь лучшую производительность и меньшую задержку, чем при анимации на основе процессора, которые используют все другие свойства.
Здесь я объединил transfrom и scaleX() значения translateX(), где scaleX задает его ширину, а translateX - его горизонтальное положение.
В качестве примечания, transform выполняет свои значения справа налево, поэтому, если кто-то поменяется местами, результат будет другим.
Фрагмент стека - вроде «нерабочий», если говорить о том, как он анимируется, и без переполнения.
.test {
display: flex;
box-sizing: border-box;
width: 384px;
border: 1px solid;
height: 48px;
position: relative;
}
.test::before {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
transform: translateX(0%) scaleX(1);
height: 2px;
background: red;
animation: running-progress 2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
@keyframes running-progress {
0% {
transform: translateX(0%) scaleX(1);
}
50% {
transform: translateX(12.5%) scaleX(0.75);
}
100% {
transform: translateX(50%) scaleX(0);
}
}<div class = "test"></div>Фрагмент стека - как ваша "рабочая" версия, используя transform
.test {
display: flex;
box-sizing: border-box;
width: 384px;
border: 1px solid;
height: 48px;
position: relative;
}
.test::before {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
transform: translateX(-50%) scaleX(0);
height: 2px;
background: red;
animation: running-progress 2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
@keyframes running-progress {
0% {
transform: translateX(-50%) scaleX(0);
}
50% {
transform: translateX(12.5%) scaleX(.75);
}
100% {
transform: translateX(50%) scaleX(0);
}
}<div class = "test"></div>Три примечания:
<div /> не является самозакрывающимся тегом, ему нужны как начальный, так и конечный теги <div></div>
значение ширины fill-available выполняет свою работу и может быть лучшим вариантом, чем приведенный ниже overflow: hidden (когда переполнение может потребоваться для другого дочернего элемента), и скоро станет вариантом, хотя оно по-прежнему экспериментальный и не рекомендуется для производства
иногда все, что нужно, это overflow: hidden, здесь применительно к вашему исходному "нерабочему" образцу
.test {
display: flex;
box-sizing: border-box;
width: 384px;
border: 1px solid;
height: 48px;
position: relative;
overflow: hidden;
}
.test::before {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 2px;
background: red;
animation: running-progress 2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
@keyframes running-progress {
0% {
margin-left: 0px;
margin-right: 100%;
}
50% {
margin-left: 25%;
margin-right: 0%;
}
100% {
margin-left: 100%;
margin-right: 0;
}
}<div class = "test"></div>
Примечание: это
::afterс двумя двоеточиями. Пока одно двоеточие будет работать, ты не должен больше так делать.