Appearance
如何实现高度自动的过渡
也许会想到 hover 前设置弹窗的高度为 0px , 移入后再把高度设为 auto 再加上过渡效果 transition 就可以实现了 事实上这是不行的,因为过渡效果必须是一个量化的值,不能是auto
方案一: max-height
使用 max-height,开始设为 0px , 移入后设置个稍微大一点的值,比如 1000px ,事实上这会有两个弊端:
- 最大值设置为多少合适呢?多少都不合适;
- 在动画开始和结束的时间不一致,试试看吧。
hover me
Lorem ipsum dolor sit amet consectetur. Doloremque explicabo rem nesciunt perferendis harum! Voluptatibus voluptate cum unde doloribus odio. Quod tempore reprehenderit voluptate corrupti nesciunt. Ratione alias doloremque facere doloribus perferendis! Pariatur minima corporis illum natus expedita. Quaerat soluta cupiditate amet nemo pariatur! Unde corrupti porro voluptates maxime at? Quas blanditiis quaerat culpa error! Laudantium. Esse modi ipsum quas reprehenderit adipisci!
对应关键代码
vue
&.btn:hover {
background-color: rgba(22, 119, 255, 0.8);
cursor: pointer;
.detail {
max-height: 1000px;
}
}
.detail {
max-height: 0px;
transition: max-height 2s;
&.btn:hover {
background-color: rgba(22, 119, 255, 0.8);
cursor: pointer;
.detail {
max-height: 1000px;
}
}
.detail {
max-height: 0px;
transition: max-height 2s;
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
方案二: scaleY
唯一不好就是内容被压缩了,如果设计师说这种效果更喜欢,那么这样就可以了。 试试看吧
hover me
Lorem ipsum dolor sit amet consectetur. Doloremque explicabo rem nesciunt perferendis harum! Voluptatibus voluptate cum unde doloribus odio. Quod tempore reprehenderit voluptate corrupti nesciunt. Ratione alias doloremque facere doloribus perferendis! Pariatur minima corporis illum natus expedita. Quaerat soluta cupiditate amet nemo pariatur! Unde corrupti porro voluptates maxime at? Quas blanditiis quaerat culpa error! Laudantium. Esse modi ipsum quas reprehenderit adipisci!
对应关键代码
vue
&.btn:hover {
background-color: rgba(22, 119, 255, 0.8);
cursor: pointer;
.detail {
transform: scaleY(1);
}
}
.detail {
transform-origin: center top;
transform: scaleY(0);
transition: transform 0.5s;
&.btn:hover {
background-color: rgba(22, 119, 255, 0.8);
cursor: pointer;
.detail {
transform: scaleY(1);
}
}
.detail {
transform-origin: center top;
transform: scaleY(0);
transition: transform 0.5s;
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
TIP
如果非要是下滑的效果呢
方案三: dispaly:grid
很遗憾的是这种动画在Safari浏览器里不支持
hover me
Lorem ipsum dolor sit amet consectetur. Doloremque explicabo rem nesciunt perferendis harum! Voluptatibus voluptate cum unde doloribus odio. Quod tempore reprehenderit voluptate corrupti nesciunt. Ratione alias doloremque facere doloribus perferendis! Pariatur minima corporis illum natus expedita. Quaerat soluta cupiditate amet nemo pariatur! Unde corrupti porro voluptates maxime at? Quas blanditiis quaerat culpa error! Laudantium. Esse modi ipsum quas reprehenderit adipisci!
对应关键代码
vue
&.btn:hover {
background-color: rgba(22, 119, 255, 0.8);
cursor: pointer;
.detail {
grid-template-rows: 1fr;
}
}
.detail {
display: grid;
grid-template-rows: 0fr;
transition: grid-template-rows 0.5s;
&.btn:hover {
background-color: rgba(22, 119, 255, 0.8);
cursor: pointer;
.detail {
grid-template-rows: 1fr;
}
}
.detail {
display: grid;
grid-template-rows: 0fr;
transition: grid-template-rows 0.5s;
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
最终js方案
是采用 Flip
库的现实思想
hover me
Lorem ipsum dolor sit amet consectetur. Doloremque explicabo rem nesciunt perferendis harum! Voluptatibus voluptate cum unde doloribus odio. Quod tempore reprehenderit voluptate corrupti nesciunt. Ratione alias doloremque facere doloribus perferendis! Pariatur minima corporis illum natus expedita. Quaerat soluta cupiditate amet nemo pariatur! Unde corrupti porro voluptates maxime at? Quas blanditiis quaerat culpa error! Laudantium. Esse modi ipsum quas reprehenderit adipisci!
对应关键代码
vue
<div class="btn" @mouseenter="onBtnMouseEnter" @mouseleave="onBtnMouseLeave">
<div class="btn" @mouseenter="onBtnMouseEnter" @mouseleave="onBtnMouseLeave">
1
ts
<script setup lang="ts">
import { ref } from 'vue'
const modalRef = ref<HTMLElement | null>(null)
const onBtnMouseEnter = () => {
const modal = modalRef.value
if (modal) {
modal.style.setProperty('height', 'auto')
const { height } = modal.getBoundingClientRect()
modal.style.setProperty('height', '0px')
modal.style.setProperty('transition', 'height .3s')
// modal.offsetHeight // 随便读取一个属性让ta强行绘制
requestAnimationFrame(() => {
modal.style.setProperty('height', `${height}px`)
})
}
}
const onBtnMouseLeave = () => {
const modal = modalRef.value
if (modal) {
modal.style.setProperty('height', '0px')
}
}
</script>
<script setup lang="ts">
import { ref } from 'vue'
const modalRef = ref<HTMLElement | null>(null)
const onBtnMouseEnter = () => {
const modal = modalRef.value
if (modal) {
modal.style.setProperty('height', 'auto')
const { height } = modal.getBoundingClientRect()
modal.style.setProperty('height', '0px')
modal.style.setProperty('transition', 'height .3s')
// modal.offsetHeight // 随便读取一个属性让ta强行绘制
requestAnimationFrame(() => {
modal.style.setProperty('height', `${height}px`)
})
}
}
const onBtnMouseLeave = () => {
const modal = modalRef.value
if (modal) {
modal.style.setProperty('height', '0px')
}
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
less
&.btn:hover {
background-color: rgba(22, 119, 255, 0.8);
cursor: pointer;
}
.detail {
z-index: 99;
position: absolute;
left: 0;
margin-top: 20px;
width: 500px;
.content {
height: 0px;
overflow: hidden;
&.btn:hover {
background-color: rgba(22, 119, 255, 0.8);
cursor: pointer;
}
.detail {
z-index: 99;
position: absolute;
left: 0;
margin-top: 20px;
width: 500px;
.content {
height: 0px;
overflow: hidden;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15