2016-10-21 10 views
2

У меня есть слайд вниз меню, которое может меняться в количестве отображаемых элементов.Почему процентная маржа с высотой и как я могу ее обойти?

Я использую обертку overflow: hidden и margin-top: -100%, чтобы скрыть меню, и переход CSS с margin-top: 0, чтобы анимировать слайд вниз.

Проблема заключается в том, что margin-top: -100%, по-видимому, подбирает явный width любого родительского элемента и игнорирует высоту содержимого.

.outer { 
 
    overflow: hidden; 
 
    border: 10px solid red; 
 
    cursor: pointer; 
 
} 
 
.outer > .slide { 
 
    margin-top: -100%; 
 
    transition-property: margin-top; 
 
    transition-duration: 1s; 
 
} 
 
.outer:hover > .slide { 
 
    margin-top: 0; 
 
} 
 
.outer.bug { 
 
    width: 100px; 
 
}
<div class="outer"> 
 
    <div class="slide"> 
 
    <ul> 
 
     <li> 
 
     Ayy 
 
     </li> 
 
     <li> 
 
     Bee 
 
     </li> 
 
     <li> 
 
     See 
 
     </li> 
 
     <li> 
 
     Dee 
 
     </li> 
 
     <li> 
 
     Eee 
 
     </li> 
 
     <li> 
 
     Eff 
 
     </li> 
 
     <li> 
 
     Gee 
 
     </li> 
 
    </ul> 
 
    </div> 
 
</div> 
 

 
<div class="outer bug"> 
 
    <div class="slide"> 
 
    <ul> 
 
     <li> 
 
     Ayy 
 
     </li> 
 
     <li> 
 
     Bee 
 
     </li> 
 
     <li> 
 
     See 
 
     </li> 
 
     <li> 
 
     Dee 
 
     </li> 
 
     <li> 
 
     Eee 
 
     </li> 
 
     <li> 
 
     Eff 
 
     </li> 
 
     <li> 
 
     Gee 
 
     </li> 
 
    </ul> 
 
    </div> 
 
</div>

Run, что фрагмент кода, и вы должны увидеть две красные коробки, курсор либо, чтобы получить слайд вниз меню.

Проблема заключается в втором поле - единственная разница в том, что у родителя установлен width: 100px;.

Если вы проверите второй блок, вы увидите, что margin-top: -100%; был рассчитан как -100px.

Фактически любая явная или унаследованная ширина против родительского div станет отрицательным.

Единственный способ, которым я нашел это, - явно указать margin-top на то же, что и высота раздвижного меню, но это связано с макетом DOM и JS, которые я действительно не хочу делать для каждого меню ,

Это ошибка в том, как браузеры обрабатывают отрицательные проценты по краю? IE11, Chrome и FX все, похоже, относятся к нему одинаково.

Есть ли лучший способ обойти это, что не требует явного расчета высоты и дополнительного Javascript?

+5

Это, как поля определены в CSS. 'margin-top', если задано процентное значение,« см. ширину содержащего блока ». https://www.w3.org/TR/CSS22/box.html#propdef-margin –

+0

@JamesDonnelly Ah, поэтому он должен использовать ширину (которая унаследована) по высоте (вычисленная из стека детей + margin), поскольку это будет круговой ссылкой. Итак, мой вопрос становится: каким-либо образом вокруг него без JS calcs? – Keith

+0

Итак, вы можете написать margin-top: -160% или более, но я не знаю, хорошая ли это паретика! возможно, это лучше, если использовать _viewport height_. –

ответ

1

Чтобы переместить элемент (независимо от его высоты) в зависимости от его собственных размеров, вы можете использовать transform:translate() вместо поля.

Итак, ваше требование по перемещению элемента вверх по его собственной высоте потребует перевода по оси Y -100%. Как так:

* { 
 
    margin: 0; 
 
    padding: 0; 
 
} 
 
.outer { 
 
    /* overflow: hidden; */ 
 
    padding: 10px; 
 
    background: red; 
 
    cursor: pointer; 
 
    position: relative; 
 
} 
 
.outer > .slide { 
 
    position: absolute; 
 
    top: 0; 
 
    left: 0; 
 
    transform: translateY(-100%); 
 
    transition-property: transform; 
 
    transition-duration: 1s; 
 
} 
 
.outer:hover > .slide { 
 
    transform: translateY(0%); 
 
}
<div class="outer"> 
 
    <div class="slide"> 
 
    <ul> 
 
     <li>Ayy</li> 
 
     <li>Bee</li> 
 
     <li>See</li> 
 
     <li>Dee</li> 
 
     <li>Eee</li> 
 
    </ul> 
 
    </div> 
 
</div>

Тогда мы можем использовать абсолютное позиционирование, чтобы удалить ребенка из потока документов.

+0

Приветствия, но это не совсем работает - перевод оставляет исходное отражение вокруг элемента, поэтому ваш отрезанный имеет внешний красный граничный div, который всегда расширяется. – Keith

+0

Тогда вам понадобится абсолютное позиционирование, и это проблема из-за «переполнения-скрытия». Это требование? –

+0

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

1

margin-top:-100% работает только при удалении границы 20px присвоен .outer, который используется дважды 10px + 10px. Поэтому мы можем использовать функцию CSS calc() для получения нашего вывода.

ul имеет значение по умолчанию padding-top:40px так это тоже используется дважды 40px + 40px, который мы должны задать 0px.

Так уль и граница является причиной для отказа от работы свойств ул margin-top:-100%;

По умолчанию:

ul{ 
display: block; 
list-style-type: disc; 
margin-before: 1em; 
margin-after: 1em; 
margin-start: 0; 
margin-end: 0; 
padding-start: 40px; 
} 

.outer { 
 
    overflow: hidden; 
 
    border: 10px solid red; 
 
    cursor: pointer; 
 
    width:auto; 
 
    height:auto; 
 
} 
 
.outer > .slide { 
 
    margin-top: calc(-26px + (-100%)); 
 
    transition-property: margin-top; 
 
    transition-duration: 1s; 
 
    background:#ccc; 
 
} 
 
.outer > .slide > ul{ 
 
    padding:0; 
 
    margin:0; 
 
} 
 
.outer:hover > .slide { 
 
    margin-top: 0; 
 
} 
 
.outer.bug { 
 
    width: 100px; 
 
}
<div class="outer"> 
 
    <div class="slide"> 
 
    <ul> 
 
     <li>Ayy</li> 
 
     <li>Bee</li> 
 
     <li>See</li> 
 
     <li>Dee</li> 
 
     <li>Eee</li> 
 
     <li>Eff</li> 
 
     <li>Gee</li> 
 
    </ul> 
 
    </div> 
 
</div> 
 

 
<div class="outer bug"> 
 
    <div class="slide"> 
 
    <ul> 
 
     <li>Ayy</li> 
 
     <li>Bee</li> 
 
     <li>See</li> 
 
     <li>Dee</li> 
 
     <li>Eee</li> 
 
     <li>Eff</li> 
 
     <li>Gee</li> 
 
    </ul> 
 
    </div> 
 
</div>

+0

@ Keith Надеюсь, это сработает. – frnt

+0

Это не так, входной сигнал по-прежнему является шириной, а не высотой - попробуйте сделать список длиннее, чем он широко, и проблема снова появляется. – Keith

+0

@Keith проверить это jsfiddle https://jsfiddle.net/fpLc76xw/ Я добавил еще несколько слов и внес изменения в calc(). Автоматически высота второй .slide ul увеличилась и вычиталась с помощью calc(), она работает. Но будет обновляться, когда я получаю вывод на другое решение. – frnt

 Смежные вопросы

  • Нет связанных вопросов^_^