Как использовать 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 (Спасибо Пол Айриш!).

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

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

3 ответов


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

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

#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% работает так, как ожидалось.

скрипка

обратите внимание, что обертка переводится на 100%, как вы заявили. Однако, кажется, что вы действительно хотите, чтобы переместить элемент 100% - width. Чтобы достичь этого, вы должны перевести ребенка также 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>

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

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

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

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

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

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

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

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>

модель Flexbox делает это довольно настраиваемый. Например, скажем, мы хотим .слайдер для перемещения справа налево, вместо этого. Все, что нам нужно сделать, это переключить flex-направление в собственность .флекс-контейнер строка-обратный, и мы сделали!

не стесняйтесь играть с ним в этом перо.

имейте в виду, что все может стать немного сложнее, если мы хотим анимации для различных типов событий. Например, я столкнулся с этой проблемой при попытке анимировать метку, когда пользователь вводит элемент ввода. Немного больше HTML и CSS необходимо, чтобы заставить его работать (я также использовал некоторые JS), но концепция та же.

вот еще перо на этот раз в контексте форму ввода.


Если вы используете решение-оболочку (как в подходе пользовательских фургонов), я предпочитаю ссылаться на 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