Skip to content

过渡

元素可以淡出、菜单可以滑入、颜色可以从一种变为另一种,实现这些效果最简单的方式是过渡(transitions)。

从这边到那边

简单示例

html
<button class="button-demo">Hover over me</button>
<style scoped>
  .button-demo {
    background-color: hsl(180, 50%, 50%);
    border: 0;
    color: white;
    font-size: 1rem;
    padding: 0.3em 1em;
    transition-property: all;
    transition-duration: 0.5s;
  }
  .button-demo:hover {
    background-color: hsl(0, 50%, 50%);
    border-radius: 1em;
  }
</style>

小结

  1. 过渡共有四个属性,均以 transistion- 开头

    • transition-property
    • transition-duration
    • transition-timing-function
    • transition-delay
  2. 开发时一般使用简写语法

    css
    transition: <transition-property> <transition-duration>
      <transition-timing-function> <transition-delay>;
  3. 过渡有两种方法触发

    • 状态变化 : hover
    • JavaScript 添加或删除影响元素样式的某个类
  4. transition 属性一般添加在元素选择器,不是添加在伪类选择器;需要过渡变化的属性则添加在伪类选择器

  5. 如果需要为不同的属性分别设置不同的过渡,可以添加多个过渡规则,以逗号分隔

定时函数

  • linear
  • ease
  • ease-in
  • ease-out
  • ease-in-out

简单示例

html
<div class="container">
  <div class="box"></div>
</div>

<style scoped>
  .container {
    position: relative;
    height: 30px;
  }
  .box {
    position: absolute;
    left: 0;
    height: 30px;
    width: 30px;
    background-color: hsl(130, 50%, 50%);
    transition: all 1s linear;
  }
  .container:hover .box {
    left: 400px;
  }
</style>

小结

出于性能考虑,应该避免对 left 属性使用过渡效果,更换使用 transform 变化。

贝塞尔曲线

待学习

非动画属性

点击按钮时在容器上添加和删除 is-open

html
<div class="dropdown" aria-haspopup="true">
  <button class="dropdown__toggle">Menu</button>
  <div class="dropdown__drawer">
    <ul class="menu" role="menu">
      <li role="menuitem">
        <a href="/features">Features</a>
      </li>
      <li role="menuitem">
        <a href="/pricing">Pricing</a>
      </li>
      <li role="menuitem">
        <a href="/support">Support</a>
      </li>
      <li role="menuitem">
        <a href="/about">About</a>
      </li>
    </ul>
  </div>
 </div>
 <p><a href="/read-more">Read more</a></p>

<script type="text/javascript">
  (function () {
    var toggle = document.getElementsByClassName('dropdown__toggle')[0];
    var dropdown = toggle.parentElement;
    toggle.addEventListener('click', function (e) {
      e.preventDefault();
      dropdown.classList.toggle('is-open');
    });
  });
 </script>
<!-- Codepen demo works fine, but Vdoing not  -->
<!-- <script type="text/javascript">
  (function () {
    var toggle = document.getElementsByClassName('dropdown__toggle')[0];
    var dropdown = toggle.parentElement;
    toggle.addEventListener('click', function (e) {
      e.preventDefault();
      dropdown.classList.toggle('is-open');
    });
  }());
 </script> -->

<style>
  .dropdown__toggle {
    display: block;
    padding: 0.5em 1em;
    border: 1px solid hsl(280, 10%, 80%);
    color: hsl(280, 30%, 60%);
    background-color: white;
    font: inherit;
    text-decoration: none;
    transition: background-color 0.2s linear;
  }
  .dropdown__toggle:hover {
    background-color: hsl(280, 15%, 95%);
  }
  .dropdown__drawer {
    position: absolute;
    display: none;
    background-color: white;
    width: 10em;
  }
  .dropdown.is-open .dropdown__drawer {
    display: block;
  }
  .menu {
    padding-left: 0;
    margin: 0;
    list-style: none;
  }
  .menu > li + li > a {
    border-top: 0;
  }
  .menu > li > a {
    display: block;
    padding: 0.5em 1em;
    color: hsl(280, 40%, 60%);
    background-color: white;
    text-decoration: none;
    transition: all 0.2s linear;
    border: 1px solid hsl(280, 10%, 80%);
  }
  .menu > li > a:hover {
    background-color: hsl(280, 15%, 95%);
    color: hsl(280, 25%, 10%);
  }
</style>

显示效果

Read more

Vdoing 内相关效果未能实现,请在 Codepen 内调试。

实现分析

  1. 找到 .dropdown_toggle 也就是 Menu 这个按钮
  2. 向上找到父元素 .dropdown
  3. .dropdown 按钮添加点击事件监听,有点击就 添加/移除 .is-open
  4. .dropdown__toggle 是哥哥,.dropdown__drawer 是弟弟,弟弟通过 display: none; 隐藏
  5. 点击哥哥(实际是点击包裹在外面的父元素),添加/移除 父元素身上的 .is-open 类,以控制弟弟 .dropdown_drawer 的 显示/隐藏

display 属性只能从 noneblock 切换,无法过渡。换用 opacity 属性,可以过渡。

扩展学习

  1. Transition Dropdown Menu CSS
  2. immediately invoked function expression (IIFE)

过渡到自动高度

代码不起作用是因为一个值不能从长度 0 过渡到 auto,因为不知道渲染以后真正的高度是多少。所以需要通过 JavaScript 来获取菜单精确的像素高度。

html
<body>
  <div class="dropdown" aria-haspopup="true">
    <button class="dropdown__toggle">Menu</button>
    <div class="dropdown__drawer">
      <ul class="menu" role="menu">
        <li role="menuitem"><a href="/features">Features</a></li>
        <li role="menuitem"><a href="/pricing">Pricing</a></li>
        <li role="menuitem"><a href="/support">Support</a></li>
        <li role="menuitem"><a href="/about">About</a></li>
      </ul>
    </div>
    <p><a href="/read-more">Read more</a></p>
    <script type="text/javascript">
      (function () {
        var toggle = document.getElementsByClassName("dropdown__toggle")[0];
        var dropdown = toggle.parentElement;
        var drawer = document.getElementsByClassName("dropdown__drawer")[0];
        var height = drawer.scrollHeight;
        toggle.addEventListener("click", function (e) {
          e.preventDefault();
          dropdown.classList.toggle("is-open");
          if (dropdown.classList.contains("is-open")) {
            drawer.style.setProperty("height", height + "px");
          } else {
            drawer.style.setProperty("height", "0");
          }
        });
      })();
    </script>
  </div>
</body>

Reference