【问题标题】:Visually slide down fixed element with items aligned at flex-end视觉上向下滑动固定元素,项目在 flex-end 对齐
【发布时间】:2017-01-06 10:44:09
【问题描述】:

我在我的移动网络应用程序中显示了一个类似于应用程序抽屉的 组件,我在其中使用带有 more 的底部导航图标来打开其他选项。

一些选项抽屉事实

  1. 上下滑动进入/退出视图
  2. 具有全屏高度
  3. 在底部垂直对齐项目
  4. 每行显示 N 个选项(与每行只有一个选项的附加图片不同)
  5. 与主底部导航放置在屏幕底部的同一 position: fixed 容器中。

我的选项抽屉的动画应该类似于在这个 iOS 动画 GIF 上可以看到的动画

https://jsfiddle.net/LL4dst15/

问题

我的抽屉正在使用 flexbox(从示例中可以看到),它将元素与交叉轴上的 flex-end 对齐以将它们显示在最底部。但问题是导航容器是固定定位的,并且有这样的z-index,它会一直显示在内容上。

translateY问题

如果我使用translateY,抽屉实际上应该滑入/滑出,但抽屉元素的位置不会改变,这意味着导航容器仍然具有抽屉+底栏的高度。这可以在我左边的小提琴示例中看到,灰色元素总是可见的。因此,这将涵盖我的实际内容,因此用户将难以与之交互。

但是我可以使用pointer-events: none;,但我认为这是一个相当丑陋的黑客,可能有问题的浏览器支持。所以我想避免它。

max-height问题

如果我使用max-height 而不是转换,那么导航容器实际上会在抽屉调整大小时调整大小。这种方法的问题是抽屉似乎没有向上/向下滑动,而是折叠作为百叶窗......原因是交叉轴对齐到弯曲端。如果我与 flex start 对齐,那么它似乎正在滑出。

我试图用自动边距解决这个问题,但似乎无法让它工作,所以我可以让 flex 开始跨轴对齐,但使用自动边距将内容推送到抽屉的底部。运气不好...

你有什么其他建议我应该如何做 CSS 以便我的抽屉会滑动并且我的容器也会调整大小?

【问题讨论】:

  • 如果您提供纯 CSS(并且在问题本身内,根据 SO 指南),您的代码示例将更易于访问。我试了一下,但花了太多时间编译你的代码。希望别人可以帮助你。祝你好运。
  • @Michael_B 为什么会这样?您应该直接在 JSFiddle 上运行代码(并更改它)。无需将它放到本地机器上并编译它。当你运行 JSFiddle 时,它​​会将 SCSS 预编译为 CSS……但对于源代码来说确实如此。我将添加主要摘录。 (顺便说一句:手动将这个相当短的 SCSS 文件更改为 CSS 也不应该花费太多时间)
  • 尝试在 jsfiddle 和 codepen.io 中编译。它没有用。非标准的 CSS 仍然存在。也许我需要更好地学习这些功能。
  • 你为什么考虑使用pointer-events: none hack?它在所有浏览器中得到广泛支持:caniuse.com/#feat=pointer-events

标签: css flexbox css-transitions slide


【解决方案1】:

我尝试使用 css 动画和关键帧; JS Fiddle

只剩下一个问题:加载页面时代码也会运行。这可以通过一些 jQuery 轻松解决。

我所做的简短版本:我为变换设置了动画: translateY() 以获得您想要的效果,然后在动画的最后 % 中,我将您的最大高度设置为:0vh。就我个人而言,我更喜欢用 jQuery 来做这件事,但是你想要一个 css 解决方案,所以你去吧。

这里是代码(CSS 现在有点乱,有所有被注释掉的东西,但清理它是你的工作):

html

Click any bottom bar item to toggle options drawer
<nav>
  <ul class="bottom-nav">
    <li>One</li>
    <li>Two</li>
    <li>Three</li>
    <li>Four</li>
  </ul>
  <ul class="extras" label="Uses 'translateY' to slide drawer">
    <li>Option</li>
    <li>Option</li>
    <li>Option</li>
    <li>Option</li>
    <li>Option</li>
    <li>Option</li>
    <li>Option</li>
    <li>Option</li>
    <li>Option</li>
    <li>Option</li>
  </ul>
</nav>
<nav>
  <ul class="bottom-nav">
    <li>One</li>
    <li>Two</li>
    <li>Three</li>
    <li>Four</li>
  </ul>
  <ul class="extras" label="Uses 'max-height' to slide drawer">
    <li>Option</li>
    <li>Option</li>
    <li>Option</li>
    <li>Option</li>
    <li>Option</li>
    <li>Option</li>
    <li>Option</li>
    <li>Option</li>
    <li>Option</li>
    <li>Option</li>
  </ul>
</nav>

css

html, body {
  background-color: #fff;
  line-height: 1.25rem;
  margin: 0;
}
nav {
  position: fixed;
  bottom: 20px;
  left: 10px;
  width: 300px;
  display: flex;
  flex-direction: column;
  background-color: #eee;
  border: 1px solid #fcc;

  ul {
    list-style: none;
    margin: 0;
    padding: 0;
    li {
      margin: 0;
      padding: 0;
    }
  }

  @mixin drawer() {
    width: 100%;
    display: flex;
    flex-flow: row wrap;
    align-content: flex-end;
    align-items: flex-start;
    cursor: default;
    background-color: #fff;
    box-shadow: 0 0 10px #999;
    overflow: hidden;
    &:before {
      content: attr(label);
      position: absolute;
      margin: 5px 0 0 10px;
      color: #999;
      font-size: 0.8125rem;
      font-style: italic;
    }
    li {
      flex-basis: 25%;
      text-align: center;
      padding: 1rem 0;
      &:hover {
        background-color: #f4f4f4;
      }
    }    
  }

  .bottom-nav {
    @include drawer();
    order: 1;
    z-index: 1;
  }

  .extras {
    @include drawer();
    order 0;
    z-index: 0;
    /* 100vh   = full height
     * 3.25rem = bottom nav bar (2×1rem padding + 1.25 line height)
     * 1.25rem = top text line height
     * 20px    = navigation fixed position bottom offset
     * 2px     = navigation container top and bottom border
     */
    height: calc(100vh - 3.25rem - 1.25rem - 20px - 2px);
    /*transform: translateY(100%);*/
    /*transition: transform 1s, opacity 0.5s;*/
    animation: closedrawer 10s forwards;
  }
  &.open {
    .extras {
      /*opacity: 1;*/
      animation: opendrawer 10s 1 forwards;
      /*transform: none;*/
      /*transition: transform 1s, opacity 0.5s 0.25s;*/
    }
  }

  + nav {
    left: 320px;

    .extras {
      /*transform: none;
      max-height: 0;
      transition: max-height 1s, opacity 0.5s 0.25s;*/
    }

    &.open {
      .extras {
        /*max-height: 100vh;
        transition: max-height 1s, opacity 1s;*/
      }
    }
  }
}
@keyframes opendrawer {
    0% {transform: translateY(100%); opacity: 1;}
    99% {background-color: blue; transform: translateY(0%); max-height: 100vh;}
    100% {background-color: blue; transform: translateY(0%);max-height: 100vh;opacity:1;}
}
@keyframes closedrawer {
  0%{transform: translateY(0%)}
   99% {background-color: red; transform: translateY(100%);max-height: 100vh; opacity: 1;}
    100% {background-color: red; transform: translateY(100%); max-height: 0vh; opacity: 0;}
}

javscript

$(function(){
    $(".bottom-nav li").click(function(evt){
    evt.preventDefault();
$(this).closest("nav").toggleClass("open");
  })
})

【讨论】:

  • 这是我可能的方法之一,但出于同样的原因(使用附加脚本),我放弃了这个想法。但这让我想到了 max-height 的最终状态。所以我最终想出了一个与原始解决方案非常相似的解决方案,我只为max-height 0s $duration 添加了过渡,这基本上延迟了最大高度的过渡,直到其他过渡完成,然后将其大小调整为 0 而没有任何过渡(0s)。
【解决方案2】:

translateY 和延迟 max-height 的解决方案

使用动画的缺点是加载时滑出的动画应该由javascript单独处理,我不喜欢。使用translateY 滑出的解决方案是在transform 完成后调整它的大小。最大高度过渡之后可以没有动画,只要完成即可。

所以滑出而不是仅仅做

transition: transform $duration; // plus opacity of you want

应该做的

transition: transform $duration, max-height 0s $duration;

这将正常完成 Y 平移,然后还将元素的高度更改为 0,这将相应地调整容器的大小,这首先是问题所在。请注意,max-height 的立即转换具有时间维度 0s,而不仅仅是一个简单的 0,它会被浏览器忽略。

如果动画足够长,用户可以在 Y 平移过程中开始点击内容,也可以将 pointer-events: none; 设置为容器,但不要忘记在子元素上将其设置为 auto,因为此属性是继承的.

这将是问题的可选解决方案。

这是resulting JSFiddle 实现了上层。

【讨论】:

    【解决方案3】:

    您应该在drawer() 之后将以下代码添加到您的.extras 类中。

    li {
        flex: 1 0 100%;
    }
    

    JSFiddle:https://jsfiddle.net/k9apwnsq/2/

    【讨论】:

    • WTF Fiddle with checkboxes? 但否则这不是我正在寻找的解决方案,因为我的选项仍应显示在列中。附加的图像只是一个抽屉容器的演示,它覆盖了内容并显示了我想要什么样的滑动。我的 Fiddle 示例选项都完全按应有的方式定位。 问题是(正如问题中明确解释的那样):任一抽屉容器未调整大小,因此它保持覆盖内容或抽屉在调整到零高度时没有视觉滑出。
    • ...与我的原始代码有什么不同?两个抽屉仍然完全相同工作相同。
    猜你喜欢
    • 2013-12-06
    • 2020-05-11
    • 2019-05-29
    • 1970-01-01
    • 1970-01-01
    • 2022-10-14
    • 1970-01-01
    • 2018-05-06
    • 2018-09-17
    相关资源
    最近更新 更多