点击查看html编辑器说明文档

拟物化开关设计edit icon

|
|
Fork(复制)
|
|
作者:
穿越者X57

👉 新版编辑器已上线,点击进行体验吧!

BUG反馈
嵌入
设置
下载
HTML
格式化
支持Emmet,输入 p 后按 Tab键试试吧!
<head> ...
展开
</head>
<body>
            
            <div class="switch">
    <label class="switch__label" for="temperature-scale">Temperature</label>
    <button class="switch__button" type="button" id="temperature-scale" title="Temperature Scale" aria-labelledby="f">
        <span class="switch__button-wrap">
            <span class="switch__shadow"></span>
            <span class="switch__shadow"></span>
            <span class="switch__inner">
                <span class="switch__options">
                    <span id="c" class="switch__option-label" aria-hidden="true">&deg;C</span>
                    <span class="switch__option-sep"></span>
                    <span id="f" class="switch__option-label" aria-hidden="true">&deg;F</span>
                </span>
            </span>
        </span>
    </button>
</div>
        
</body>
SCSS
格式化
            
            * {
    border: 0;
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}
:root {
    --hue: 223;
    --bg: hsl(var(--hue),10%,90%);
    --fg: hsl(var(--hue),10%,10%);
    --trans-dur: 0.3s;
    --trans-timing: cubic-bezier(0.65,0,0.35,1);
    font-size: calc(60px + (120 - 60) * (100vw - 280px) / (3840 - 280));
}
body,
button {
    font: 1em/1.5 "DM Sans", sans-serif;
}
body {
    background-color: var(--bg);
    color: var(--fg);
    display: flex;
    height: 100vh;
    transition:
        background-color var(--trans-dur),
        color var(--trans-dur);
}
.switch {
    display: flex;
    margin: auto;

    &__button,
    &__label {
        -webkit-tap-highlight-color: transparent;
    }
    &__button {
        background-color: transparent;
        border-radius: 0.75em;
        box-shadow: 0 0 0 0.125em hsla(var(--hue),90%,50%,0);
        cursor: pointer;
        outline: transparent;
        width: 100%;
        height: 100%;
        -webkit-appearance: none;
        appearance: none;
        z-index: 1;
        transition: box-shadow calc(var(--trans-dur) / 2);

        &:focus-visible {
            box-shadow: 0 0 0 0.125em hsla(var(--hue),90%,50%,1);
        }
        &,
        &-wrap {
            display: block;
            position: relative;
        }
        &-wrap {
            box-shadow:
                0 0.0625em 0.0625em hsl(var(--hue),10%,65%) inset,
                0 -0.0625em 0.0625em hsl(var(--hue),10%,87.5%) inset,
                0 0.25em 0.25em hsl(var(--hue),10%,70%) inset;
            border-radius: 0.75em;
            width: 3.1875em;
            height: 1.5em;
            transition: box-shadow var(--trans-dur);
        }
    }
    &__label {
        overflow: hidden;
        margin-inline-end: 0.75em;
        position: absolute;
        width: 1px;
        height: 1px;
    }
    &__inner,
    &__options,
    &__options:before,
    &__options:after,
    &__shadow {
        position: absolute;
    }
    &__inner,
    &__options {
        background-color: hsl(var(--hue),10%,90%);
    }
    &__inner {
        box-shadow: 0 -0.125em 0.25em hsl(var(--hue),10%,80%) inset;
        border-radius: 0.5em;
        display: block;
        perspective: 20em;
        inset: 0.25em;
        transition:
            background-color var(--trans-dur),
            box-shadow var(--trans-dur);
    }
    &__options {
        border-radius: inherit;
        box-shadow: 0 0 1px hsl(0,0%,100%) inset;
        display: flex;
        justify-content: space-around;
        font-size: 0.5em;
        line-height: 2;
        width: 100%;
        height: 100%;
        transform: translateX(-0.125rem) rotateY(-15deg);
        transition:
            background-color var(--trans-dur),
            box-shadow var(--trans-dur),
            transform var(--trans-dur) var(--trans-timing);

        &:before,
        &:after {
            content: "";
            display: block;
            top: 0;
            width: 45%;
            height: 100%;
            transition: opacity var(--trans-dur) var(--trans-timing);
        }
        &:before {
            border-radius: 0.5rem 0 0 0.5rem;
            box-shadow:
                0 1px 0.0625rem hsla(var(--hue),10%,10%,0.7) inset,
                0.125rem 0.25rem 0.25rem hsla(var(--hue),10%,10%,0.3) inset;
            mask-image: linear-gradient(-90deg,hsla(var(--hue),10%,90%,0),hsl(var(--hue),10%,90%));
            left: 0;
        }
        &:after {
            border-radius: 0 0.5rem 0.5rem 0;
            box-shadow:
                0 1px 0.0625rem hsla(var(--hue),10%,10%,0.7) inset,
                -0.125rem 0.25rem 0.25rem hsla(var(--hue),10%,10%,0.3) inset;
            mask-image: linear-gradient(90deg,hsla(var(--hue),10%,90%,0),hsl(var(--hue),10%,90%));
            right: 0;
            opacity: 0;
        }
    }
    &__option {
        &-label {
            color: var(--fg);
            font-weight: 500;
            text-align: center;
            width: 100%;
            text-shadow:
                0 -1px 0 hsl(var(--hue),10%,40%),
                0 1px 0 hsl(0,0%,100%);
            transition:
                color var(--trans-dur),
                text-shadow var(--trans-dur);

            &:last-child {
                color: hsl(var(--hue),10%,60%);
            }
        }
        &-sep {
            background-color: hsl(var(--hue),10%,75%);
            box-shadow: 1px 0 0 hsl(0,0%,100%);
            width: 1px;
            min-width: 1px;
            margin: auto 0;
            height: 0.75rem;
            transition:
                background-color var(--trans-dur),
                box-shadow var(--trans-dur);
        }
    }
    &__shadow {
        border-radius: 0.375em 0.875em 0.375em 0.375em / 0.375em 0.625em 0.125em 0.375em;
        box-shadow: 0 0 0 0.125em hsla(var(--hue),10%,10%,0.7);
        display: block;
        top: 0.375em;
        left: 0.375em;
        width: 1.25em;
        height: 0.75em;
        transform: rotate(0);
        transform-origin: 1em 0.375em;
        transition:
            box-shadow var(--trans-dur) var(--trans-timing),
            transform var(--trans-dur) var(--trans-timing);
        z-index: -1;
    }
    &__shadow + &__shadow {
        border-radius: 0.875em 0.375em 0.375em 0.375em / 0.625em 0.375em 0.375em 0.125em;
        box-shadow: 0 0 0.25em 0.125em hsla(var(--hue),10%,10%,0.7);
        right: 0.375em;
        left: auto;
        transform: rotate(7.5deg);
        transform-origin: 0.5em 0.375em;
    }
    &__button[aria-labelledby="f"] &__options {
        transform: translateX(0.125rem) rotateY(15deg);

        &:before {
            opacity: 0;
        }
        &:after {
            opacity: 1;
        }
    }
    &__button[aria-labelledby="f"] &__option-label {
        color: hsl(var(--hue),10%,60%);

        &:last-child {
            color: var(--fg);
        }
    }
    &__button[aria-labelledby="f"] &__shadow {
        box-shadow: 0 0 0.25em 0.125em hsla(var(--hue),10%,10%,0.7);
        transform: rotate(-7.5deg);
    }
    &__button[aria-labelledby="f"] &__shadow + &__shadow {
        box-shadow: 0 0 0 0.125em hsla(var(--hue),10%,10%,0.7);
        transform: rotate(0);
    }
}

/* Dark theme */
@media (prefers-color-scheme: dark) {
    :root {
        --bg: hsl(var(--hue),10%,30%);
        --fg: hsl(var(--hue),10%,90%);
    }
    .switch {
        &__button {
            box-shadow: 0 0 0 0.125em hsla(var(--hue),90%,70%,0);

            &:focus-visible {
                box-shadow: 0 0 0 0.125em hsla(var(--hue),90%,70%,1);
            }
            &-wrap {
                box-shadow:
                    0 0.0625em 0.0625em hsl(var(--hue),10%,5%) inset,
                    0 -0.0625em 0.0625em hsl(var(--hue),10%,27.5%) inset,
                    0 0.25em 0.25em hsl(var(--hue),10%,20%) inset;
            }
        }
        &__inner,
        &__options {
            background-color: hsl(var(--hue),10%,30%);
        }
        &__inner {
            box-shadow: 0 -0.125em 0.25em hsl(var(--hue),10%,20%) inset;
        }
        &__options {
            box-shadow: 0 0 1px hsl(var(--hue),10%,50%) inset;
        }
        &__option {
            &-label {
                text-shadow:
                    0 -1px 0 hsl(var(--hue),10%,10%),
                    0 1px 0 hsl(var(--hue),10%,50%);
    
                &:last-child {
                    color: hsl(var(--hue),10%,20%);
                }
            }
            &-sep {
                background-color: hsl(var(--hue),10%,20%);
                box-shadow: 1px 0 0 hsl(var(--hue),10%,50%);
            }
        }
        &__button[aria-labelledby="f"] &__option-label {
            color: hsl(var(--hue),10%,20%);
        }
        &__shadow
        &__button[aria-labelledby="f"] &__shadow + &__shadow {
            box-shadow: 0 0 0 0.125em hsla(var(--hue),10%,10%,0.9);
        }
        &__shadow + &__shadow,
        &__button[aria-labelledby="f"] &__shadow {
            box-shadow: 0 0 0.25em 0.125em hsla(var(--hue),10%,10%,0.9);
        }
    }
}
        
JS
格式化
            
            window.addEventListener("DOMContentLoaded",() => {
    const rockerSwitch = new RockerSwitch("#temperature-scale");
});

class RockerSwitch {
    /** Button used for this switch */
    button: HTMLButtonElement | null;

    /**
     * @param buttonEl CSS selector of the button to use
     */
    constructor(buttonEl: string) {
        this.button = document.querySelector(buttonEl);
        this.button?.addEventListener("click",this.temperatureScaleToggle.bind(this));
    }
    private _temperatureScale: TemperatureScale = "f";
    /** Selected temperature scale */
    get temperatureScale(): TemperatureScale {
        return this._temperatureScale;
    }
    set temperatureScale(value: TemperatureScale) {
        this._temperatureScale = value;
        this.button?.setAttribute("aria-labelledby",this._temperatureScale);
    }
    /** Set the temperature scale to °C or °F. */
    temperatureScaleToggle(): void {
        this.temperatureScale = this.temperatureScale === "c" ? "f" : "c";
    }
}
type TemperatureScale = "c" | "f";
        
预览
控制台