Vue3+Tailwind实现按钮从w-full到w-fit的宽度平滑过渡
解决Vue3 + Tailwind按钮从w-full到w-fit的平滑过渡问题
问题原因
CSS无法在width: 100%(对应Tailwind的w-full)和width: fit-content(对应Tailwind的w-fit)之间生成平滑过渡动画——因为fit-content是基于元素内容动态计算的尺寸,浏览器无法计算这两个值之间的过渡中间帧,导致宽度变化突兀。
方案一:固定宽度模拟(适合图标尺寸固定场景)
如果你的加载图标尺寸固定,直接给加载状态的按钮设置一个刚好容纳图标的固定宽度(比如w-12,可根据图标大小调整),让按钮从w-full过渡到固定宽度,实现平滑收缩:
<button :class="`bg-red text-white rounded-full transition-all duration-300 ease-in ${ loadingLogin ? 'w-12' : 'w-full' }`"> <span v-if="!loadingLogin">Login</span> <spinner-icon v-else class="mx-auto" /> </button>
- 给加载图标添加
mx-auto确保它在固定宽度的按钮中居中,视觉效果和w-fit一致。 - 可根据你的图标尺寸调整
w-12,比如图标是w-5 h-5,可以用w-10。
方案二:动态计算宽度(适合图标尺寸不固定场景)
如果加载图标尺寸不固定,用Vue的DOM引用和动态样式来计算并设置按钮的目标宽度:
<template> <button ref="loginBtn" :class="`bg-red text-white rounded-full transition-all duration-300 ease-in ${ loadingLogin ? '' : 'w-full' }`" :style="loadingLogin ? { width: `${targetWidth}px` } : {}" > <span v-if="!loadingLogin">Login</span> <spinner-icon v-else ref="spinner" /> </button> </template> <script setup> import { ref, watch, nextTick } from 'vue' const loadingLogin = ref(false) const loginBtn = ref(null) const spinner = ref(null) const targetWidth = ref(0) watch(loadingLogin, (isLoading) => { if (isLoading) { // 等待DOM更新,确保加载图标已渲染完成 nextTick(() => { if (spinner.value && loginBtn.value) { // 获取按钮的左右内边距,加上图标宽度得到目标宽度 const btnStyles = window.getComputedStyle(loginBtn.value) const paddingX = parseInt(btnStyles.paddingLeft) + parseInt(btnStyles.paddingRight) targetWidth.value = spinner.value.offsetWidth + paddingX } }) } else { targetWidth.value = 0 } }) </script>
- 通过
nextTick确保加载图标已经渲染,才能正确获取其宽度。 - 计算时包含按钮的左右内边距,保证按钮宽度刚好容纳图标和内边距,避免图标被挤压。
内容的提问来源于stack exchange,提问作者dakairus
相关产品推荐
相关产品推荐

