Подтвердить что ты не робот

Как использовать transform: translateX для перемещения дочернего элемента по горизонтали на 100% по родительскому элементу

Все,

Я хотел бы использовать translateX для анимации дочернего элемента на 100% пути через него родительского (то есть от левого края до правого края).

Задача состоит в том, что проценты в translateX относятся к самому элементу, а не к родительскому.

Итак, например, если мой html выглядит так:

<div id="parent">
    <div id="child">
</div>

И мой CSS вроде этого (префикс поставщика не указан):

#parent {
    position: relative;
    width: 300px;
    height: 100px;
    background-color: black;
}
#child {
    position: absolute;
    width: 20px;
    height: 100px;
    background-color:red;
    transform: translateX(100%);
}

Это не сработает - ребенок перемещает только 20px (100% от себя), а не полностью через родителя. (Вы можете видеть это на jsfiddle):

enter image description here

Я могу это сделать:

#child {
    position: absolute;
    width: 20px;
    height: 100px;
    background-color:red;
    -webkit-transform: translateX(300px) translateX(-100%);
    transform: translateX(300px) translateX(-100%);
}

Это работает (см. здесь снова на jsfiddle), поскольку он сначала перемещает дочернего 300px (полная ширина родительский), минус 20px (ширина ребенка). Однако это зависит от того, какой родитель имеет фиксированный известный размер пикселя.

enter image description here

Однако в моем отзывчивом дизайне я не знаю ширины родителя, и он изменится.

Я знаю, что я могу использовать left:0 и right:0, но производительность анимации влево/вправо намного хуже, чем translateX (Спасибо Пол Ирланд!).

Есть ли способ сделать это?

Спасибо заранее.

4b9b3361

Ответ 1

Я не публиковал свою идею изначально, потому что это связано с созданием дополнительного слоя HTML и ожидаемыми лучшими решениями.

Так как этого не произошло, я объясняю свой комментарий. Я имел в виду следующее:

#parent {
    position: relative;
    width: 300px;
    height: 100px;
    background-color: black;
}
#wrapper {
    position: absolute;
    width: 100%;
    height: 100px;
    border: solid 1px green;
    transition: all 1s;
}
#wrapper:hover {
    -webkit-transform: translateX(100%);
    transform: translateX(100%);
}
#child {
    position: absolute;
    width: 20px;
    height: 100px;
    background-color:red;
}
#wrapper:hover #child {
    -webkit-transform: translateX(-100%);
    transform: translateX(-100%);
}

Так как оболочка имеет 100% -ную ширину родителя, перевод на 100% работает, как ожидалось.

fiddle

Обратите внимание, что обертка переводится на 100%, как вы заявляли. Однако кажется, что вы действительно хотите переместить элемент на 100% - ширину. Чтобы достичь этого, вы должны перевести ребенка также на 100% (теперь это относится к ширине ребенка) в противоположном направлении.

Коррекция: дочерний объект должен делиться свойством перехода оболочки:

#parent {
    position: relative;
    width: 300px;
    height: 100px;
    background-color: black;
}
#wrapper {
    position: absolute;
    width: 100%;
    height: 100px;
    border: solid 1px green;
    transition: all 5s;
}
#wrapper:hover {
    transform: translateX(100%);
}
#child {
    position: absolute;
    width: 50px;
    height: 100px;
    background-color:red;
    transition: inherit;
}
#wrapper:hover #child {
    transform: translateX(-100%);
}
<div id="parent">
    <div id="wrapper">
        <div id="child"></div>
    </div>
</div>

Ответ 2

Там довольно крутое решение этой проблемы, используя Flexbox. Ключ должен использовать свойство flex-grow.

Скажем, у вас есть HTML-код, который выглядит так:

<div class="flex-container">
  <div class="flex-spacer"></div>
  <div class="slider"></div>
</div>

Сначала дайте .flex-container базовый дисплей: свойство flex и задайте его гибкое направление для строки. Установите расположение дочерних элементов относительно, поэтому они будут располагаться рядом друг с другом внутри контейнера .flex.

По умолчанию свойство flex-grow устанавливается равным 0, что мы и хотим в начале. Это означает, что .flex-spacer и .slider будут иметь только свои нормальные размеры. Мы просто сохраняем .flex-spacer пустым, и он будет иметь ширину 0.

Теперь для анимации. Нам нужно только два правила CSS, чтобы заставить его работать: добавьте переход к .flex-spacer и установите flex-grow на 1 на .flex-spacer во время какого-то события. Второе правило дает всю неиспользованную ширину внутри .flex-контейнера по ширине .flex-spacer, а первое правило оживляет изменение ширины. Элемент .slider подталкивается к краю .flex-контейнера.

CSS выглядит примерно так: я добавил фон для .flex-spacer, чтобы сделать его присутствие немного более очевидным и установить flex-grow до 1, когда пользователь наводит курсор на .flex-container:

body * {
  box-sizing: border-box;
}

.flex-container {
  cursor: pointer;
  display: flex;
  flex-flow: row nowrap;
  width: 100%;
  border: 2px solid #444;
  border-radius: 3px;
}

.flex-spacer,
.slider {
  flex-grow: 0;
  position: relative;
}

.slider {
  padding: 25px;
  background-color: #0DD;
}

.flex-spacer {
  background-color: #DDD;
  transition: all .4s ease-out;
}

.flex-container:hover .flex-spacer {
  flex-grow: 1;
}
<div class="flex-container">
  <div class="flex-spacer"></div>
  <div class="slider"></div>
</div>

Ответ 3

Если вы используете обертку-решение (например, в подходе пользовательских фургонов), я предпочитаю ссылаться на 1% вместо 100% от родительской ширины и умножать переведенное значение на 100. Таким образом, вы избегаете проблем с кликабельными элементами рядом с дочерний элемент.

Например, если вы хотите перевести дочерний элемент в центр родительского элемента:

#wrapper {
  position: absolute;
  left: 0;
  top: 0;

  width: 1%;
  overflow: visible;

  transform: translateX(5000%);
}

#child {
  transform: translateX(-50%);
}

HTML

<div id="parent">
  <div id="wrapper">
    <div id="child">

    </div>
  </div>
  <a onclick="alert('im still clickable')">
    click me
  </a>
</div>

http://codepen.io/anon/pen/BLxYXO