过渡
元素可以淡出、菜单可以滑入、颜色可以从一种变为另一种,实现这些效果最简单的方式是过渡(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>
小结
过渡共有四个属性,均以
transistion-
开头transition-property
transition-duration
transition-timing-function
transition-delay
开发时一般使用简写语法
csstransition: <transition-property> <transition-duration> <transition-timing-function> <transition-delay>;
过渡有两种方法触发
- 状态变化
: hover
- JavaScript 添加或删除影响元素样式的某个类
- 状态变化
transition
属性一般添加在元素选择器,不是添加在伪类选择器;需要过渡变化的属性则添加在伪类选择器如果需要为不同的属性分别设置不同的过渡,可以添加多个过渡规则,以逗号分隔
定时函数
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>
显示效果
Vdoing 内相关效果未能实现,请在 Codepen 内调试。
实现分析
- 找到
.dropdown_toggle
也就是 Menu 这个按钮 - 向上找到父元素
.dropdown
- 给
.dropdown
按钮添加点击事件监听,有点击就 添加/移除.is-open
类 .dropdown__toggle
是哥哥,.dropdown__drawer
是弟弟,弟弟通过display: none;
隐藏- 点击哥哥(实际是点击包裹在外面的父元素),添加/移除 父元素身上的
.is-open
类,以控制弟弟.dropdown_drawer
的 显示/隐藏
display
属性只能从 none
到 block
切换,无法过渡。换用 opacity
属性,可以过渡。
扩展学习
- Transition Dropdown Menu CSS
- 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>