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

В чистом CSS можно установить маржу, равную высоте текущего элемента?

У меня есть вертикальный стек элементов, к которому пользователь может добавить один, нажав кнопку, примерно так.

<ol>
  <li><textarea></textarea></li>
  <li><textarea></textarea></li>
</ol>
<a data-action="additem">Add another</a>

Я пытаюсь написать анимацию CSS, чтобы при вставке нового li "Добавить другой" плавно переместился в новое место отдыха. Фиксированная высота тегов li не является опцией, и я стараюсь избегать использования анимации max-height, поскольку она может иметь странные эффекты макета.

Я понял, что я мог бы анимировать margin-bottom от чего-то до 0 и иметь желаемый эффект, но я не могу понять, как в CSS выражать то, что мне нужна текущая высота элемента, к которому применяется это правило, Проценты измеряются относительно ширины элемента, и это не то, что мне нужно здесь, и я не могу придумать умный трюк, используя calc или тому подобное, чтобы выразить то, что я хочу в браузере.

Предложения?

ИЗМЕНИТЬ

Я использую шаблон с повторной привязкой для добавления элементов в список. JS только подталкивает другой объект в наблюдаемый массив, а структура обрабатывает фактическую вставку DOM. Тег li имеет на нем следующий CSS, чтобы заставить его войти гладко:

animation: append forwards .5s;

И append определяется как:

@keyframes append {
    from {
        transform: translateX(10%);
        opacity: 0;
        margin-bottom: _____;
    }

    to {
        transform: none;
        opacity: 1;
        margin-bottom: 0;
    }
}
4b9b3361

Ответ 1

Не в настоящее время...

Я часто сталкивался с этой неутешительной проблемой, всегда пытаясь либо анимировать нечисловое значение, доступ к определенному свойству текущего элемента как значения анимации, либо анимировать неопределенное значение указанному, Как правило, мне всегда приходится возвращаться к какой-то не совсем совершенной анимации max-height (как вы уже упоминали) или использовать смесь CSS и JavaScript/jQuery.

Для вашей проблемы есть несколько вариантов, но ни один из них не подходит именно вам.


только версия css (с использованием дублированной разметки и другой анимации)

Один трюк, часто используемый с использованием только CSS-хаков, заключается в дублировании разметки — в этом случае, ссылка iteself — и поместите его в родительские обертки, которые будут включены или выключены различными способами. Недостатки этого метода заключаются в том, что вы получаете довольно уродливую разметку, а в этом конкретном случае - номер пули, который появляется резким образом (из-за необходимости переместить анимацию непрозрачности с li на textarea).

Преимущество этого метода состоит в том, что, перемещая ссылку внутри li, вы можете использовать -100% по оси y с помощью перевода или другого метода смещения. Как ни странно, хотя я не могу понять, что вычисляет translateY(-100%) на основе... , он, кажется, не является родительской высотой, возможно, это высота самого себя. По этой причине я обновил скрипту, чтобы вместо этого использовать bottom и относительное позиционирование, хотя в Firefox (на Mac) это глючит ненадолго.

Кажется, что translateY вычисляет процент, основанный на собственной высоте, поэтому, чтобы обойти эту проблему, мне пришлось использовать абсолютную позицию и заставить слой ссылки принимать те же размеры как li... раздражает, так как он включает z-индексацию textarea над ссылкой и внутренний span для смещения текста ссылки, но по крайней мере он работает.

Следующий код работает в последнем Firefox и будет работать в других современных браузерах, если бы все различные префиксы браузера были правильно использованы для определения ключевых кадров анимации, у меня нет времени, чтобы установить их все прямо сейчас.

Разметка:

<ol class="list">
  <li><textarea></textarea><a class="add" href="#"><span>Add another</span></a></li>
  <li><textarea></textarea><a class="add" href="#"><span>Add another</span></a></li>
</ol>

CSS

ol li {
  position: relative;
}
ol li .add {
  display: none;
}
ol li:last-child .add {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  top: 0;
  width: 100%;
  height: 100%;
  display: block;
  animation-duration: 1s;
  animation-name: slide;
}

ol li:last-child .add span {
    position: absolute;
    bottom: -20px;
}

.list li textarea {
  position: relative;
  animation-duration: 1s;
  animation-name: append;
  z-index: 1;
}

@keyframes append {
  from {
    transform: translateX(10%);
    opacity: 0;
  }
  to {
    transform: none;
    opacity: 1;
  }
}

@keyframes slide {
  from {
    transform: translateY(-100%);
  }
  to {
    transform: none;
  }
}


версия javascript (транслируемые с помощью кода)

http://jsfiddle.net/7m8F9/1/

Следующие, очевидно, не учитывают тот факт, что вы используете механизм шаблонов для управления вашими DOM-манипуляциями, но весь код должен работать правильно - это до и после высоты списка (чтобы вычислить разницу в высота) и событие для запуска в точке добавления нового элемента списка.

К сожалению, пока все это невозможно сделать в чистом CSS, по крайней мере, не настолько, насколько я видел, возможно, однажды calc выровнял...? Или, возможно, если какой-то способ вводится для ссылки на текущие размеры элементов, а не только на смещение родителя.

Следует отметить, что у меня не было Internet Explorer, чтобы проверить это, но все остальные современные браузеры выглядят счастливыми.

Разметка:

<ol class="list">
  <li><textarea></textarea></li>
  <li><textarea></textarea></li>
</ol>
<div class="add">
  <a href="#">Add another</a>
</div>

javascript (с jQuery):

function prefix(){
  for ( var a = ['Webkit','Moz','O','ms'], i=0, l = a.length; i<l; i++ ) {
    if ( document.body.style[a[i]+'AnimationName'] !== undefined ) {
      return { js: a[i], css: '-' + a[i].toLowerCase() + '-' };
    }
  }
  return { css:'', js:'' };
}

$(function(){
  $('.add a').click(function(e){
    e.preventDefault();
    var pref = prefix(),
      link = $(this).parent(), 
      list = $('.list'),
      lihi = list.height(),
      liad = $('<li><textarea></textarea></li>').appendTo(list),
      lihd = lihi - list.height();
      link.css(pref.css + 'transform', 'translateY(' + lihd + 'px)');
    setTimeout(function(){link.addClass('translate-zero transition-all');},0);
    setTimeout(function(){
      link.css(pref.css + 'transform', '');
      link.removeClass('translate-zero transition-all');
    },500);
  });
});

CSS

.transition-all {
  -webkit-transition: all 0.5s;
  -moz-transition: all 0.5s;
  -ms-transition: all 0.5s;
  -o-transition: all 0.5s;
  transition: all 0.5s;
}

.translate-zero {
  -webkit-transform: translateY(0) !important;
  -moz-transform: translateY(0) !important;
  -ms-transform: translateY(0) !important;
  -o-transform: translateY(0) !important;
  transform: translateY(0) !important;
}

.list li {
  animation-duration: 1s;
  animation-name: append;
}

@keyframes append {
  from {
    transform: translateX(10%);
    opacity: 0;
  }
  to {
    transform: none;
    opacity: 1;
  }
}


версия для редизайна

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

example of top right link

Ответ 2

Самое простое решение, о котором я мог подумать, - это.

Когда вы добавляете новый элемент li, просто добавьте его в dom.

liMarkup = '<li><textarea></textarea></li>'
$('ol').append(liMarkup);
$('ol').find('li').last().css('display','none');
$('ol').find('li').last().show('fast');

Это будет работать согласно вашему требованию:) Я надеюсь, что это поможет.

Работа Jsfiddle

EDIT: легко и просто сделать это в JS.