css 奶油风格小组件
核心实现在于box-shadow 阴影的控制和背景色的选择
Switch
<script lang='ts' setup>
</script>
<template>
<div class="custom-wrapper p-10">
<div class="container px-12 py-6 rounded-10px">
<div class="milk-switch w-24 inline-block mr-12">
<input id="switch-1" type="checkbox" class="display-none">
<label for="switch-1" class="inline-block w-full h-12 cursor-pointer rounded-6 relative flex items-center" />
</div>
<div class="milk-switch w-24 inline-block">
<input id="switch-2" type="checkbox" class="display-none" checked>
<label for="switch-2" class="inline-block w-full h-12 cursor-pointer rounded-6 relative flex items-center" />
</div>
</div>
</div>
</template>
<style lang='scss' scoped>
.custom-wrapper {
--primary-light: #8abdff;
--primary: #6d5dfc;
--primary-dark: #5b0eeb;
--white: #FFFFFF;
--greyLight-1: #E4EBF5;
--greyLight-2: #c8d0e7;
--greyLight-3: #bec8e4;
--greyDark: #9baacf;
$shadow: .3rem .3rem .6rem var(--greyLight-2), -.2rem -.2rem .5rem var(--white);
$inner-shadow: inset .2rem .2rem .5rem var(--greyLight-2), inset -.2rem -.2rem .5rem var(--white);
background-color: var(--greyLight-1);
.container {
box-shadow:.8rem .8rem 1.4rem var(--greyLight-2), -.2rem -.2rem 1.8rem var(--white);
.milk-switch {
label {
box-shadow: $shadow;
&::after {
content: '';
position: absolute;
left: .4rem;
width: 2.1rem;
height: 2.1rem;
border-radius: 50%;
background-color: var(--greyDark);
transition: all 0.4s ease;
}
&::before {
content: '';
width: 100%;
height: 100%;
border-radius: inherit;
background: linear-gradient(330deg, var(--primary-dark) 0%, var(--primary) 50%, var(--primary-light) 100%);
opacity: 0;
transition: all .4s ease;
}
}
& input:checked {
& ~ label {
&::before { opacity: 1; }
&::after {
left: 57%;
background: var(--greyLight-1);
}
}
}
}
}
}
</style>
Checkbox
<script lang='ts' setup>
</script>
<template>
<div class="custom-wrapper p-10">
<div class="container px-12 py-6 rounded-10px">
<div class="checkbox w-24 inline-block mr-12">
<input id="checkbox-1" type="checkbox" class="display-none">
<label for="checkbox-1" class="flex items-center w-12 h-12 justify-center rounded-6">
<i class="i-ri:check-line">done</i></label>
</div>
<div class="checkbox w-24 inline-block">
<input id="checkbox-2" type="checkbox" class="display-none" checked>
<label for="checkbox-2" class="flex items-center w-12 h-12 justify-center rounded-6">
<i class="i-ri:check-line">done</i></label>
</div>
</div>
</div>
</template>
<style lang='scss' scoped>
.custom-wrapper {
--primary-light: #8abdff;
--primary: #6d5dfc;
--primary-dark: #5b0eeb;
--white: #FFFFFF;
--greyLight-1: #E4EBF5;
--greyLight-2: #c8d0e7;
--greyLight-3: #bec8e4;
--greyDark: #9baacf;
$shadow: .3rem .3rem .6rem var(--greyLight-2), -.2rem -.2rem .5rem var(--white);
$inner-shadow: inset .2rem .2rem .5rem var(--greyLight-2), inset -.2rem -.2rem .5rem var(--white);
background-color: var(--greyLight-1);
.container {
box-shadow:.8rem .8rem 1.4rem var(--greyLight-2), -.2rem -.2rem 1.8rem var(--white);
.checkbox {
label {
box-shadow: $shadow;
i {
font-size: 1.8rem;
font-weight: bold;
color: var(--greyDark);
transition: all 0.3s ease;
}
&:hover i {
color: var(--primary);
}
}
& input:checked {
& ~ label {
box-shadow: $inner-shadow;
i {
color: var(--primary);
}
}
}
}
}
}
</style>
Radio
<script lang='ts' setup>
</script>
<template>
<div class="custom-wrapper p-10">
<div class="container px-12 py-6 rounded-10px">
<div class="w-24 inline-block mr-12">
<input id="radio-1" type="radio" name="radio" value="1" class="display-none">
<label for="radio-1" class="relative flex justify-center items-center cursor-pointer w-12 h-12 rounded-6" />
</div>
<div class="w-24 inline-block">
<input id="radio-2" type="radio" name="radio" value="2" checked class="display-none">
<label for="radio-2" class="relative flex justify-center items-center cursor-pointer w-12 h-12 rounded-6" />
</div>
</div>
</div>
</template>
<style lang='scss' scoped>
.custom-wrapper {
--primary-light: #8abdff;
--primary: #6d5dfc;
--primary-dark: #5b0eeb;
--white: #FFFFFF;
--greyLight-1: #E4EBF5;
--greyLight-2: #c8d0e7;
--greyLight-3: #bec8e4;
--greyDark: #9baacf;
$shadow: .3rem .3rem .6rem var(--greyLight-2), -.2rem -.2rem .5rem var(--white);
$inner-shadow: inset .2rem .2rem .5rem var(--greyLight-2), inset -.2rem -.2rem .5rem var(--white);
background-color: var(--greyLight-1);
.container {
box-shadow:.8rem .8rem 1.4rem var(--greyLight-2), -.2rem -.2rem 1.8rem var(--white);
label {
box-shadow: $shadow;
&::after {
content: '';
position: absolute;
width: 1.4rem;
height: 1.4rem;
border-radius: 50%;
background-color: var(--greyDark);
transition: all 0.4s ease;
}
}
& input:checked {
& ~ label {
box-shadow: $inner-shadow;
&::after {
background: var(--primary);
}
}
}
}
}
</style>
Button
<script lang='ts' setup>
</script>
<template>
<div class="custom-wrapper p-10">
<div class="container px-12 py-6 rounded-10px">
<div class="btn btn__primary w-60 h-16 rounded-4 flex items-center justify-center transition-all duration-300 ease select-none cursor-pointer mr-6 mb-6">
<span class="text-lg font-bold">
Button
</span>
</div>
<div class="btn btn__secondary w-60 h-16 rounded-4 flex items-center justify-center transition-all duration-300 ease select-none cursor-pointer">
<span class="text-lg font-bold">
Button
</span>
</div>
</div>
</div>
</template>
<style lang='scss' scoped>
.custom-wrapper {
--primary-light: #8abdff;
--primary: #6d5dfc;
--primary-dark: #5b0eeb;
--white: #FFFFFF;
--greyLight-1: #E4EBF5;
--greyLight-2: #c8d0e7;
--greyLight-3: #bec8e4;
--greyDark: #9baacf;
$shadow: .3rem .3rem .6rem var(--greyLight-2), -.2rem -.2rem .5rem var(--white);
$inner-shadow: inset .2rem .2rem .5rem var(--greyLight-2), inset -.2rem -.2rem .5rem var(--white);
background-color: var(--greyLight-1);
.container {
box-shadow:.8rem .8rem 1.4rem var(--greyLight-2), -.2rem -.2rem 1.8rem var(--white);
.btn {
box-shadow: $shadow;
&__primary {
background-color: var(--primary);
box-shadow:inset .2rem .2rem 1rem var(--primary-light), inset -.2rem -.2rem 1rem var(--primary-dark), $shadow;
color: var(--greyLight-1);
&:hover { color: var(--white); }
&:active {
box-shadow:inset .2rem .2rem 1rem var(--primary-dark), inset -.2rem -.2rem 1rem var(--primary-light);
}
}
&__secondary {
color: var(--greyDark);
&:hover { color: var(--primary); }
&:active {
box-shadow: $inner-shadow;
}
}
}
}
}
</style>
Tab
<script lang='ts' setup>
</script>
<template>
<div class="custom-wrapper p-10">
<div class="container px-12 py-6 rounded-10px">
<div class="segmented-control w-full h-16 rounded-4 flex items-center relative px-2">
<input id="tab-1" class="display-none" type="radio" name="radio2" value="3" checked>
<label for="tab-1" class="segmented-control__1 flex-1 h-14 text-lg flex items-center justify-center cursor-pointer transition-all duration-500 ease">
<p>Tab 1</p></label>
<input id="tab-2" class="display-none" type="radio" name="radio2" value="4">
<label for="tab-2" class="segmented-control__2 flex-1 h-14 text-lg flex items-center justify-center cursor-pointer transition-all duration-500 ease">
<p>Tab 2</p></label>
<input id="tab-3" class="display-none" type="radio" name="radio2" value="5">
<label for="tab-3" class="segmented-control__3 flex-1 h-14 text-lg flex items-center justify-center cursor-pointer transition-all duration-500 ease">
<p>Tab 3</p></label>
<div class="segmented-control__color h-12 rounded-3.2 absolute left-2 transition-transform duration-300 ease" />
</div>
</div>
</div>
</template>
<style lang='scss' scoped>
.custom-wrapper {
--primary-light: #8abdff;
--primary: #6d5dfc;
--primary-dark: #5b0eeb;
--white: #FFFFFF;
--greyLight-1: #E4EBF5;
--greyLight-2: #c8d0e7;
--greyLight-3: #bec8e4;
--greyDark: #9baacf;
$shadow: .3rem .3rem .6rem var(--greyLight-2), -.2rem -.2rem .5rem var(--white);
$inner-shadow: inset .2rem .2rem .5rem var(--greyLight-2), inset -.2rem -.2rem .5rem var(--white);
background-color: var(--greyLight-1);
.container {
box-shadow:.8rem .8rem 1.4rem var(--greyLight-2), -.2rem -.2rem 1.8rem var(--white);
.segmented-control {
box-shadow: $shadow;
input:checked + label {
transition: all 0.5s ease;
color: var(--primary);
font-weight: bold;
}
label {
color: var(--greyDark);
&:hover {
color: var(--primary);
font-weight: bold;
}
}
&__color {
box-shadow: $inner-shadow;
pointer-events: none;
width: calc(calc(100% - 1rem) / 3);
}
#tab-1:checked ~ .segmented-control__color {
transform: translateX(0);
}
#tab-2:checked ~ .segmented-control__color {
transform: translateX(100%);
}
#tab-3:checked ~ .segmented-control__color {
transform: translateX(200%);
}
}
}
}
</style>
Input
<script lang='ts' setup>
</script>
<template>
<div class="custom-wrapper p-10">
<div class="container px-12 py-6 rounded-10px">
<div class="form mb-12">
<input type="text" class="form__input w-80 h-16 border-none rounded-4 px-6 bg-none " placeholder="请输入...">
</div>
<div class="search relative flex items-center">
<input type="text" class="search__input w-80 h-16 border-none rounded-4 pl-12 pr-6 bg-none " placeholder="查询...">
<span class="i-ic:round-search absolute text-8 left-3 transition-color duration-300 ease" />
</div>
</div>
</div>
</template>
<style lang='scss' scoped>
.custom-wrapper {
--primary-light: #8abdff;
--primary: #6d5dfc;
--primary-dark: #5b0eeb;
--white: #FFFFFF;
--greyLight-1: #E4EBF5;
--greyLight-2: #c8d0e7;
--greyLight-3: #bec8e4;
--greyDark: #9baacf;
$shadow: .3rem .3rem .6rem var(--greyLight-2), -.2rem -.2rem .5rem var(--white);
$inner-shadow: inset .2rem .2rem .5rem var(--greyLight-2), inset -.2rem -.2rem .5rem var(--white);
background-color: var(--greyLight-1);
.container {
box-shadow:.8rem .8rem 1.4rem var(--greyLight-2), -.2rem -.2rem 1.8rem var(--white);
input {
box-shadow: $inner-shadow;
color: var(--greyDark);
&::placeholder {
color: var(--greyLight-3);
}
&:focus {
outline: none;
box-shadow: $shadow;
}
}
.search {
span {
color: var(--greyDark);
}
input:focus {
outline: none;
box-shadow: $shadow;
& + span {
color: var(--primary)
}
}
}
}
}
</style>
Alert
<script lang='ts' setup>
</script>
<template>
<div class="custom-wrapper p-10">
<div class="container px-12 py-6 rounded-10px">
<div class="alert w-full flex items-center h-16 rounded-4 justify-between justify-self-center">
<div class="p-4 text-xl font-bold icon-left">
<span class="i-gis:color" />
</div>
<p class="flex-1 text-lg px-2 m-0">
some tips.....
</p>
<div class="p-4 text-xl font-bold icon-right cursor-pointer">
<span class="i-iconamoon:close-light" />
</div>
</div>
</div>
</div>
</template>
<style lang='scss' scoped>
.custom-wrapper {
--primary-light: #8abdff;
--primary: #6d5dfc;
--primary-dark: #5b0eeb;
--white: #FFFFFF;
--greyLight-1: #E4EBF5;
--greyLight-2: #c8d0e7;
--greyLight-3: #bec8e4;
--greyDark: #9baacf;
$shadow: .3rem .3rem .6rem var(--greyLight-2), -.2rem -.2rem .5rem var(--white);
$inner-shadow: inset .2rem .2rem .5rem var(--greyLight-2), inset -.2rem -.2rem .5rem var(--white);
background-color: var(--greyLight-1);
.container {
box-shadow:.8rem .8rem 1.4rem var(--greyLight-2), -.2rem -.2rem 1.8rem var(--white);
.alert {
box-shadow: $shadow;
.icon-left {
color: var(--primary);
}
p {
color: var(--greyDark);
}
.icon-right {
color: var(--greyDark);
}
}
}
}
</style>
Slider
<script lang='ts' setup>
import { ref } from 'vue'
const rangeValue = ref(50)
const sliderBox = ref()
const sliderBtn = ref()
const sliderColor = ref()
const sliderTooltip = ref()
</script>
<template>
<div class="custom-wrapper pt-10 px-10 pb-20">
<div class="slider flex self-center flex-col">
<div ref="sliderBox" class="slider__box w-full h-4 cursor-pointer relative flex justify-center items-center rounded-4">
<span ref="sliderBtn" class="slider__btn pointer-events-none w-8 h-8 rounded-4 absolute z-100 flex items-center justify-center translate-x--4" :style="{ left: `${rangeValue}%` }" />
<span ref="sliderColor" class="slider__color h-full absolute left-0 z-50 rounded-inherit" :style="{ width: `${rangeValue}%` }" />
<span ref="sliderTooltip" class="slider__tooltip absolute top-10 h-10 w-12 rounded-2 flex items-center justify-center text-lg opacity-0 transition-opacity duration-300 ease translate-x--6" :style="{ left: `${rangeValue}%` }">{{ `${rangeValue}%` }}</span>
<input v-model="rangeValue" type="range" class="w-full absolute left-0 top-0 z-300 border-none m-0 opacity-0" :min="0" :max="100">
</div>
</div>
</div>
</template>
<style lang='scss' scoped>
.custom-wrapper {
--primary-light: #8abdff;
--primary: #6d5dfc;
--primary-dark: #5b0eeb;
--white: #FFFFFF;
--greyLight-1: #E4EBF5;
--greyLight-2: #c8d0e7;
--greyLight-3: #bec8e4;
--greyDark: #9baacf;
$shadow: .3rem .3rem .6rem var(--greyLight-2), -.2rem -.2rem .5rem var(--white);
$inner-shadow: inset .2rem .2rem .5rem var(--greyLight-2), inset -.2rem -.2rem .5rem var(--white);
background-color: var(--greyLight-1);
.slider {
&__box {
box-shadow: $inner-shadow;
}
&__btn {
background-color: var(--white);
box-shadow: 0px .1rem .3rem 0px var(--greyLight-3);
&::after {
content: '';
position: absolute;
width: .8rem;
height: .8rem;
border-radius: 50%;
box-shadow: $inner-shadow;
}
}
&__color {
background: var(--primary);
background: linear-gradient(-1deg, var(--primary-dark) 0%, var(--primary) 50%, var(--primary-light) 100%);
}
&__tooltip {
color: var(--primary);
box-shadow: $shadow;
}
&:hover .slider__tooltip {opacity: 1;}
}
}
</style>
Icon Button
<script lang='ts' setup>
</script>
<template>
<div class="custom-wrapper p-10">
<div class="container py-4 px-8 rounded-4 flex items-center">
<div class="icon-item w-16 h-16 rounded-8 flex items-center justify-center text-8 cursor-pointer transition-all duration-500 ease mr-8">
<span class="i-solar:home-outline" />
</div>
<div class="icon-item w-16 h-16 rounded-8 flex items-center justify-center text-8 cursor-pointer transition-all duration-500 ease mr-8">
<span class="i-emojione-monotone:person-bowing" />
</div>
<div class="icon-item w-16 h-16 rounded-8 flex items-center justify-center text-8 cursor-pointer transition-all duration-500 ease">
<span class="i-uil:setting" />
</div>
</div>
</div>
</template>
<style lang='scss' scoped>
.custom-wrapper {
--primary-light: #8abdff;
--primary: #6d5dfc;
--primary-dark: #5b0eeb;
--white: #FFFFFF;
--greyLight-1: #E4EBF5;
--greyLight-2: #c8d0e7;
--greyLight-3: #bec8e4;
--greyDark: #9baacf;
$shadow: .3rem .3rem .6rem var(--greyLight-2), -.2rem -.2rem .5rem var(--white);
$inner-shadow: inset .2rem .2rem .5rem var(--greyLight-2), inset -.2rem -.2rem .5rem var(--white);
background-color: var(--greyLight-1);
.container {
box-shadow:.8rem .8rem 1.4rem var(--greyLight-2), -.2rem -.2rem 1.8rem var(--white);
.icon-item {
box-shadow: $shadow;
color: var(--greyDark);
&:active {
box-shadow: $inner-shadow;
color: var(--primary);
}
&:hover {
color: var(--primary);
}
}
}
}
</style>
Paused/Resume button
所需知识点如下:
<script lang='ts' setup>
</script>
<template>
<div class="custom-wrapper p-10">
<div class="container px-12 py-16 rounded-4 flex items-center justify-center relative">
<input type="checkbox" class="w-24 h-24 m-2 z-100 absolute opacity-0">
<span class="circle__btn w-24 h-24 flex items-center justify-center m-2 rounded-12 text-5xl relative cursor-pointer relative z-50">
<span class="transition-opacity duration-200 linear absolute pause i-carbon:pause-filled" />
<span class="transition-opacity duration-200 linear absolute play i-carbon:play-filled-alt" />
</span>
<span class="circle__back-1 w-24 h-24 rounded-12 blur-1 absolute" />
<span class="circle__back-2 w-24 h-24 rounded-12 blur-1 absolute" />
</div>
</div>
</template>
<style lang='scss' scoped>
.custom-wrapper {
--primary-light: #8abdff;
--primary: #6d5dfc;
--primary-dark: #5b0eeb;
--white: #FFFFFF;
--greyLight-1: #E4EBF5;
--greyLight-2: #c8d0e7;
--greyLight-3: #bec8e4;
--greyDark: #9baacf;
$shadow: .3rem .3rem .6rem var(--greyLight-2), -.2rem -.2rem .5rem var(--white);
$inner-shadow: inset .2rem .2rem .5rem var(--greyLight-2), inset -.2rem -.2rem .5rem var(--white);
background-color: var(--greyLight-1);
@keyframes waves {
0% {
transform: scale(1);
opacity: 1;
}
50% {
opacity: 1;
}
100% {
transform: scale(2);
opacity: 0;
}
}
.container {
box-shadow:.8rem .8rem 1.4rem var(--greyLight-2), -.2rem -.2rem 1.8rem var(--white);
.circle__btn {
color: var(--primary);
background-color: var(--greyLight-1);
box-shadow: 0.3rem 0.3rem 0.6rem var(--greyLight-2), -0.2rem -0.2rem 0.5rem var(--white);
.pause {
opacity: 0;
}
.play {
opacity: 1;
}
}
.circle__back-1 {
box-shadow: 0.4rem 0.4rem 0.8rem var(--greyLight-2), -0.4rem -0.4rem 0.8rem var(--white);
background: linear-gradient(to bottom right, var(--greyLight-2) 0%, var(--white) 100%);
animation: waves 4s linear infinite;
animation-play-state: paused;
}
.circle__back-2 {
box-shadow: 0.4rem 0.4rem 0.8rem var(--greyLight-2), -0.4rem -0.4rem 0.8rem var(--white);
animation: waves 4s linear 2s infinite;
animation-play-state: paused;
}
input:checked ~ .circle__btn {
.pause {
opacity: 1;
}
.play {
opacity: 0;
}
}
input:checked ~ .circle__back-1, input:checked ~ .circle__back-2 {
animation-play-state: running;
}
}
}
</style>