自适应宽度

flyKot2025/10/27

效果预览

Welcome to

分析

  • 切换动画的实现

进入时添加类名 .movein ,等动画执行完毕后将该类名删掉,退出时添加.moveout 类名,执行完毕后删掉 整个元素 ,同时该元素记得设置为 block

  • 宽度变化动画的实现

承载文字内容的span宽度应为 width: max-content; 保持最大宽度,这样才能用 span.scrollWidth 获取到真正的内容宽度

HTML

  <div class="layout_flip_text_box">
        Welcome to <div class="layout_flip_shake_text">
        </div>
    </div>

CSS

body,
html {
    padding: 0;
    margin: 0;
    width: 100vw;
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
}

.layout_flip_text_box {
    font-weight: 600;
    font-size: 34px;
    display: flex;
    justify-content: flex-start;
    align-items: baseline;
    gap: 6px;
}

.layout_flip_shake_text {
    padding: 6px 6px;
    box-shadow: 0 1px 3px 0 #0000001a, 0 1px 2px -1px #0000001a;
    border: 1px solid #c9c9c9;
    border-radius: 6px;
    box-sizing: border-box;
    height: 3rem;
    line-height: 1;
    overflow: hidden;
    white-space: nowrap;
    transition: width 0.5s ease;
}

.layout_flip_t {
    width: max-content;
    display: block;
    transition: filter 0.5s ease;
}

.movein {
    animation: text_in 0.5s ease-in forwards;
}

.moveout {
    animation: text_out 0.3s ease-out forwards;
}

@keyframes text_in {
    0% {
        opacity: 0.2;
        filter: blur(10px);
        transform: translateY(-100%);
    }

    100% {
        opacity: 1;
        filter: blur(0);
        transform: translateY(0);
    }
}

@keyframes text_out {
    0% {
        opacity: 1;
        filter: blur(0);
        transform: translateY(0);
    }

    100% {
        opacity: 0.2;
        filter: blur(10px);
        transform: translateY(100%);
    }
}

JavaScript

const textArr = ["Cursor", "QWEN", "Navicat", "Nocobase"]
let index = 0
function updateWidth(span, container) {
    const sWidth = span.scrollWidth
    container.style.width = ((sWidth + 14) + "px")
}
function updateData() {
    const container = document.querySelector(".layout_flip_shake_text")
    const span_before = document.querySelector(".layout_flip_t")
    if (span_before) {
        span_before.classList.add("moveout")
        const newSpanAfter = document.createElement("span")
        newSpanAfter.className = "layout_flip_t"
        newSpanAfter.classList.add("movein")
        newSpanAfter.innerHTML = textArr[index]
        container.appendChild(newSpanAfter)
        updateWidth(newSpanAfter, container)
        setTimeout(() => {
            span_before.remove()
            if (index < textArr.length - 1) {
                index++
            } else {
                index = 0
            }
        }, 200);
    } else {
        const newSpanBefore = document.createElement("span")
        newSpanBefore.className = "layout_flip_t"
        newSpanBefore.classList.add("movein")
        newSpanBefore.innerHTML = textArr[index]
        container.appendChild(newSpanBefore)
        updateWidth(newSpanBefore, container)
        setTimeout(() => {
            newSpanBefore.classList.remove("movein")
            index++
        }, 500);
    }

}
updateData()
setInterval(() => {
    updateData()
}, 3000);