2016-10-21 53 views
2

我有一个CSS滑动下拉菜单,可以在显示的元素数量上有所不同。为什么使用高度的保证金最高百分比以及如何解决该问题?

我使用overflow: hidden包装和margin-top: -100%来隐藏菜单,并使用margin-top: 0进行CSS转换以向下滑动动画。

问题似乎是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>

运行该代码段,你应该看到两个红色箱子,鼠标移到要么趴下菜单中的幻灯片。

问题是第二个盒子 - 唯一的区别是父母有width: 100px;集合。

如果您检查第二个框,您应该看到margin-top: -100%;已计算为-100像素。

事实上,对父div的任何显式或继承宽度将成为负边距。

我发现它的唯一方法是明确设置margin-top与滑动菜单的高度相同,但涉及到DOM布局和JS,我并不想为每个菜单执行此操作。

这是一个浏览器如何处理margin-top负数百分比的错误? IE11,Chrome和FX似乎都以同样的方式对待它。

有没有更好的解决方法,不需要明确的高度计算和额外的Javascript?

+5

这是利润率如何在CSS定义。 'margin-top',如果给定一个百分比值,则指“包含块的宽度”。 https://www.w3.org/TR/CSS22/box.html#propdef-margin –

+0

@JamesDonnelly啊,所以它必须使用宽度(这是继承)的高度(计算从一堆儿童+保证金),因为这将是一个循环参考。那么我的问题就变成了:没有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

然后你需要绝对定位,这是一个问题,因为'overflow-hidden'。这是一个要求吗? –

+0

是的,虽然在我的代码片段中,它只是一个非常丑陋的红色边框,在我的实际代码中,包装本身是绝对定位的,并提供UI提示,如滑动下来的内容上的投影,直到动画完成。 – Keith

1

margin-top:-100%只有当我们删除20px分配的.outer的边界时才有效,它被使用两次10px + 10px。所以我们可以在这里使用CSS calc()函数来获取我们的输出。

ul有一个默认padding-top:40px所以这也是使用两次40px + 40px,我们必须设置为0px

所以UL和边界是不工作的margin-top:-100%;

缺省UL属性的原因:

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 Hope这个工程。 – frnt

+0

它没有,calc的输入仍然是宽度,而不是高度 - 尝试使列表长于宽度,问题再次出现。 – Keith

+0

@Keith检查这个jsfiddle https://jsfiddle.net/fpLc76xw/我已经添加了几个li并对calc()进行了更改。第二个.slide ul的自动高度增加了,并且使用calc()减去了它,它起作用。但是会随着我在另一个解决方案上的输出而更新。 – frnt

相关问题