记录 css

96 阅读13分钟

一些CSS使用的记录,详情参考 CSS 参考手册 | 菜鸟教程 (runoob.com)

CSS 教程 | 菜鸟教程 (runoob.com)

ICSS案例参考学习 GitHub - chokcoco/iCSS: 不止于 CSS

动画库 CSS Animation Kit (angrytools.com)

anime.js • JavaScript animation engine (animejs.com)

图片动画库:

imagehover.css- 纯CSS3鼠标滑过图片效果动画库,44种鼠标滑过效果 ciar4n/imagehover.css: Pure CSS Image Hover Effect Library (github.com)

TiltEffect 是一款让图像跟随鼠标产生微妙立体倾斜效果的插件,使其有层次感和深度感。 codrops/ImageTiltEffect: A subtle tilt effect for images. The idea is to move and rotate semi-transparent copies with the same background image in order to create a subtle motion or depth effect. (github.com)

Magnifier 是一款实用纯js制作的图片放大镜插件。它有以下一些特定:mark-rolich/Magnifier.js: Javascript library enabling magnifying glass effect on an images (github.com)

css背景(background)

-   background-color:red;//背景色
-   background-size:80px 60px; 检索或设置对象的背景图像的尺寸大小
-   background-image:url('bgdesert.jpg');//背景图片
-   background-repeat:no-repeat  // 设置或检索对象的背景图像如何铺排填充。必须先指定background-image属性 
-   background-position:center //设置或检索对象的背景图像位置。必须先指定background-image属性。
-   background-image: linear-gradient(to right,#e66465, #9198e5); // 线性渐变 从左边开始的线性渐变。起点是红色,慢慢过渡到黄色

边框(border)和轮廓(outline)

/* 边框宽度 | 边框样式 | 边框颜色 */  
border: medium solid green; //设置对象边框的特性。
outline:#00FF00 dotted thick; //设置或检索对象外的线条轮廓。
border-radius: 15px 50px 30px 5px; //圆角边框。(左上角,右上角,右下角,左下角)
box-shadow: 10px 10px 5px #888888; // 方框添加一个或多个阴影

媒体查询

媒体查询(Media Queries)使用媒体查询 - CSS:层叠样式表 | MDN

  • 移动端优先开发
    先写默认样式(移动端),再用 min-width 适配大屏。
  • 桌面端优先开发
    先写桌面样式,再用 max-width 适配小屏。
@media (max-width: 768px) { ... }  /* 小屏幕 (手机) */
@media (min-width: 769px) and (max-width: 1024px) { ... }  /* 平板 */
@media (min-width: 1025px) { ... }  /* 桌面端 */

@media (orientation: portrait) {  /* 竖屏 */
  body { background: pink; }
}

@media (orientation: landscape) {  /* 横屏 */
  body { background: lightgreen; }
}

@media (min-resolution: 2dppx) {
  img {
    content: url('image@2x.png'); /* 在 Retina 屏使用高清图 */
  }
}

/* 同时满足 */
@media (min-width: 600px) and (max-width: 1200px) {
  p { font-size: 18px; }
}

/* 满足任意一个 */
@media (max-width: 500px), (orientation: landscape) {
  body { color: red; }
}

body {
    background-color:#fff;
}

// max-height,max-width,min-height,min-width
/* 屏幕宽度小于等于 600px 时生效 */
@media (max-width: 600px) {
  body {
    background-color: lightblue;
  }
}


flex 盒子模型

.box{
  display: flex;//容器都指定为Flex布局。
  
  flex-direction: row | row-reverse | column | column-reverse;//flex-direction属性决定主轴的方向
-   row(默认值):主轴为水平方向,起点在左端。
-   row-reverse:主轴为水平方向,起点在右端。
-   column:主轴为垂直方向,起点在上沿。
-   column-reverse:主轴为垂直方向,起点在下沿。

  flex-wrap: nowrap | wrap | wrap-reverse; //如果一条轴线排不下,如何换行
-    nowrap(默认):不换行。
-    wrap:换行,第一行在上方。
-    wrap-reverse:换行,第一行在下方。

  justify-content: flex-start | flex-end | center | space-between | space-around; //主轴上的对齐方式。
-   flex-start(默认值):左对齐
-   flex-end:右对齐
-   center: 居中
-   space-between:两端对齐,项目之间的间隔都相等。
-   space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。

  align-items: flex-start | flex-end | center | baseline | stretch; //交叉轴上如何对齐
-   flex-start:交叉轴的起点对齐。
-   flex-end:交叉轴的终点对齐。
-   center:交叉轴的中点对齐。
-   baseline: 项目的第一行文字的基线对齐。
-   stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。
}

定位

h2 {
    position:absolute;
    left:100px;
    top:150px;
}
sticky:粘性定位 粘性定位的元素是依赖于用户的滚动,在 **position:relative** 与 **position:fixed** 定位之间切换。
fixed :Fixed定位使元素的位置与文档流无关,因此不占据空间。Fixed定位的元素和其他元素重叠。
relative:相对定位元素的定位是相对其正常位置。
absolute:绝对定位的元素的位置相对于最近的已定位父元素,如果元素没有已定位的父元素,那么它的位置相对于<html>:

//子绝父相
<style>
    .header {
        position: relative;
        height: 105px;
        background-color: pink;
    }
    .logo {
        position: absolute;
        top: 25px;
        left: 0;
        height: 175px;
        width: 56px;
    }
</style>
 
<body>
    <div class="header w">
        <div class="logo"></div>
    </div>
</body>

文本(text) 鼠标 (cursor)

h1 {
    font-size: 12px; //字体大小
  
    font-style:normal | italic | oblique; //字体样式
-   normal  标准的字体样式
-   italic  斜体的字体样式。    
-   oblique 倾斜的字体样式。

    font-weight:normal | bold | 100-900; //字体粗细
    
    color:#FF0000;//颜色
    
    text-align:center; //文本对齐
-   left:左对齐(默认值)
-   center:居中对齐
-   right:右对齐

    text-decoration:none; //文本修饰
-   none:默认值,无任何修饰(最常用)
-   underline:下划线,例如链接a标签自带的下划线(常用)
-   overline:上划线(几乎不用)
-   line-through:删除线(不常用)

    // text-overflow 文本溢出属性
    text-overflow: ellipsis;
    overflow: hidden; 

    text-indent:10px; // 文本缩进
    letter-spacing: 3px; // 字母间距
    word-spacing:3px; // 字间距
    
    line-height:20px; // 行高
    
    text-shadow: h-shadow v-shadow blur color; //文本阴影
-   h-shadow:水平阴影的位置,正负值均可(必需)
-   v-shadow:垂直阴影的位置,正负值均可(必需)
-   blur:模糊的距离(可选)
-   color:阴影的颜色(可选)

//鼠标样式
    cursor: default; 
-   default:默认光标(通常是一个箭头)
-   pointer:光标呈现为指示链接的指针(一只手)
-   crosshair:光标呈现为十字线。
-   move:此光标指示某对象可被移动。
-   text:此光标指示文本。
-   wait:此光标指示程序正忙(通常是一只表或沙漏)。
-   help:此光标指示可用的帮助(通常是一个问号或一个气球)。
}

css 伪类

CSS 伪类 | 菜鸟教程 (runoob.com)

a:link {color:#FF0000;} /* 未访问的链接 */
a:visited {color:#00FF00;} /* 已访问的链接 */
a:hover {color:#FF00FF;} /* 鼠标划过链接 */
a:active {color:#0000FF;} /* 已选中的链接 */

**注意:**  在CSS定义中,a:hover 必须被置于 a:link 和 a:visited 之后,才是有效的。
**注意:**  在 CSS 定义中,a:active 必须被置于 a:hover 之后,才是有效的。
**注意:**  伪类的名称不区分大小写。

隔行换色

image.png

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        ul li:nth-child(odd) {
            background-color: red;
        }

        ul li:nth-child(even) {
            background-color: green;
        }
    </style>
</head>

<body>
    <ul>
        <li>未来可期1</li>
        <li>未来可期2</li>
        <li>未来可期3</li>
        <li>未来可期4</li>
        <li>未来可期5</li>
        <li>未来可期6</li>
        <li>未来可期7</li>
        <li>未来可期8</li>
        <li>未来可期9</li>
        <li>未来可期10</li>
    </ul>
</body>
</html>

响应式导航栏实例

image.png

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>

<ul class="topnav">
  <li><a class="active" href="#home">主页</a></li>
  <li><a href="#news">新闻</a></li>
  <li><a href="#contact">联系</a></li>
  <li class="right"><a href="#about">关于</a></li>
</ul>

<div style="padding:0 16px;">
  <h2>响应式导航栏实例</h2>
  <p>在屏幕宽度小于 600px 会重置导航栏。</p>
  <h4>重置浏览器窗口大小,查看效果。</h4>
</div>

</body>
 <style>
   body {margin: 0;}

ul.topnav {
    list-style-type: none;
    margin: 0;
    padding: 0;
    overflow: hidden;
    background-color: #333;
}

ul.topnav li {float: left;}

ul.topnav li a {
    display: block;
    color: white;
    text-align: center;
    padding: 14px 16px;
    text-decoration: none;
}

ul.topnav li a:hover:not(.active) {background-color: #111;}

ul.topnav li a.active {background-color: #4CAF50;}

ul.topnav li.right {float: right;}

@media screen and (max-width: 600px){
    ul.topnav li.right, 
    ul.topnav li {float: none;}
}
</style>
</html>

三角型

image.png

<div class="arrow-box">
    <div class="triangular"></div>
</div>

<style>
.arrow-box {
  position: relative;
  width: 300px;
  height: 160px;
  background: #f0f9ff;
  border: 2px solid #1598d9;
  border-radius: 6px;
  line-height: 160px;
}

.arrow-box::after,
.arrow-box::before {
  position: absolute;
  // bottom: 100%;  // 上箭头
  // left: calc(45% + 14px); 

  left: 100%;
  top: calc(45% + 14px);

  border: solid transparent;
  content: "";
  height: 0;
  width: 0;
  pointer-events: none;
}

.arrow-box::after {
  border-color: transparent;
  border-width: 12px;

  // border-bottom-color: #fff;  //// 上箭头
  // margin-left: -12px;

  border-left-color: #fff;
  margin-top: -12px;
}

.arrow-box::before {
  border-color: transparent;
  border-width: 15px;

  // border-bottom-color: #1598d9;  // 上箭头
  // margin-left: -15px;

  border-left-color: #1598d9;
  margin-top: -15px;
}

.triangular {
  // 三角形
  width: 0;
  height: 0;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  border-top: 20px solid lightblue; //  把其他的颜色变为transparent(透明色)可形成三角形
  border-left: 20px solid transparent;
  border-right: 20px solid transparent;
  border-bottom: 20px solid transparent;
}
</style>

过度

20240724_171025.gif

<h1>过度</h1>

<style scoped>
h1 {
    /* transition: all 2s; */
    transition: width 2s, color 3s, background 4s;
    color: red;
    width: 100px;
    background: #000;
}

h1:hover {
    width: 300px;
    color: blue;
    background: red;
}
</style>

2d/3d旋转

20240724_164846.gif

<div class="dd">转换</div>
 
<style >
.dd {
    width: 100px;
    height: 100px;
    background-color: #f00;
    transition: all 1s ease-in-out;
}

.dd:hover {
    /* 2d 移动(平移)translate()方法,根据左(X轴)和顶部(Y轴)位置给定的参数,从当前元素位置移动。 */
    /* transform: translate(50px, 100px); */

    /* 3d 移动(平移)translate()方法 x轴,y轴,z轴 */
    /* transform: translate3d(50px,100px,0); */

    /* 2d 旋转 rotate()方法,在一个给定度数顺时针旋转的元素。负值是允许的,这样是元素逆时针旋转。 */
    /* transform: rotate(180deg); */
    /* 3d转换 */
    /* transform: rotate3d(1, 2, 3, 180deg); */

    /* 缩放 scale()方法 ,该元素增加或减少的大小,取决于宽度(X轴)和高度(Y轴)的参数: */
    /* transform: scale(2, 2); */
    /* transform: scale3d(2, 2, 2); */

    /* 换倾斜转 skew()方法,该元素对X轴和Y轴应用倾斜转换: */
    /* transform: skew(30deg, 20deg); */

    /* matrix()方法,有六个参数,包含旋转,缩放,移动(平移)和换倾斜转: */
    /* transform: matrix(0.866, 0.5, -0.5, 0.866, 100, 10); */
}
</style>

animejs

npm install animejs --save

可参考示例 Documentation | anime.js (animejs.com)

多阶段的时间线动画

20240828_114358.gif

<template>
  <div class="container">
    <div class="box" ref="box"></div>
  </div>
</template>

<script setup>
import { onMounted, ref } from 'vue';
import anime from 'animejs/lib/anime.es.js';

const box = ref(null);

onMounted(() => {
  const timeline = anime.timeline({
    easing: 'easeInOutExpo', // 动画缓动函数
    duration: 1000, // 动画持续时间
    loop: true // 循环播放动画
  });

  timeline
    .add({
      targets: box.value,
      translateX: 250,
      scale: 2,
      backgroundColor: '#FF0000'
    })
    .add({
      targets: box.value,
      rotate: '1turn',
      borderRadius: '50%',
      duration: 2000
    })
    .add({
      targets: box.value,
      translateY: 100,
      scale: 1,
      backgroundColor: '#0000FF',
      offset: '-=1500' // 在前一个动画未完成前开始此动画
    })
    .add({
      targets: box.value,
      translateX: 0,
      rotate: '0turn',
      backgroundColor: '#00FF00',
      borderRadius: '0%',
      duration: 1500
    });
});

</script>

<style scoped>
.container {
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.box {
  width: 100px;
  height: 100px;
  background-color: #FF00FF;
  position: relative;
}
</style>

路径动画和关键帧结合

20240828_114913.gif

<template>
  <div class="container">
    <svg viewBox="0 0 500 500">
      <path id="motionPath" fill="none" stroke="lightgrey" stroke-width="2"
        d="M10 80 Q 95 10 180 80 T 330 80 Q 415 150 500 80" />
      <circle ref="circle" r="10" fill="red"></circle>
    </svg>
  </div>
</template>

<script setup>
import { onMounted, ref } from 'vue';
import anime from 'animejs/lib/anime.es.js';

const circle = ref(null);

onMounted(() => {
  anime({
    targets: circle.value,
    translateX: anime.path('#motionPath').x,
    translateY: anime.path('#motionPath').y,
    easing: 'easeInOutQuad',
    duration: 5000,
    loop: true,
    keyframes: [
      { r: 5, fill: '#FF0000' },  // 缩小并变红
      { r: 10, fill: '#00FF00' }, // 变大并变绿
      { r: 15, fill: '#0000FF' }  // 变得更大并变蓝
    ]
  });
});


</script>

<style scoped>
.container {
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

svg {
  width: 100%;
  height: auto;
}
</style>

混合3D变换和CSS属性动画

20240828_115412.gif

<template>
  <div class="container">
    <div class="box" ref="box"></div>
  </div>
</template>

<script setup>
import { onMounted, ref } from 'vue';
import anime from 'animejs/lib/anime.es.js';

const box = ref(null);

onMounted(() => {
  anime({
    targets: box.value,
    translateZ: 100,
    rotateX: '1turn',
    rotateY: '1turn',
    backgroundColor: [
      { value: '#FF0000', duration: 1000 },
      { value: '#00FF00', duration: 1000 },
      { value: '#0000FF', duration: 1000 }
    ],
    opacity: [
      { value: 0.5, duration: 1000 },
      { value: 1, duration: 1000 }
    ],
    duration: 3000,
    easing: 'easeInOutExpo',
    loop: true,
    direction: 'alternate'
  });
});

</script>

<style scoped>
.container {
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  perspective: 1000px;
  /* 必须为3D变换提供透视效果 */
}

.box {
  width: 100px;
  height: 100px;
  background-color: #3498db;
  opacity: 1;
}
</style>

图片动画效果

20240815_105656.gif

    <div class="wrapper">
      <div class="scenes" tabindex="0">
        <div class="scene-1">
          <h2 class="scene-title">Qui-Gon Jinn and Obi-Wan Kenobi</h2>
        </div>
        <div class="scene-2">
          <h2 class="scene-title">Darth Maul</h2>
        </div>
      </div>
    </div>

//css
@keyframes scene-transition {
  25% {
    filter: brightness(100%);
  }

  100% {
    filter: brightness(100%);
    -webkit-mask-size: 1800%;
  }
}

.scenes {
  position: relative;
  width: 500px;
  height: 500px;
  outline: 2px solid #ccc;
  cursor: pointer
}

.scene-1,
.scene-2 {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-repeat: repeat;
  background-position: center;
}

.scene-1 {
  background-image:
    radial-gradient(circle, #fff3 10%, transparent 20%),
    url(https://img-s-msn-com.akamaized.net/tenant/amp/entityid/AA1oEjiP.img?w=768&h=480&m=6&x=394&y=103&s=381&d=381);
}

.scene-2 {
  background-image: url(https://img-s-msn-com.akamaized.net/tenant/amp/entityid/AA1oGYlS.img?w=768&h=783&m=6);
  filter: brightness(0%);
  -webkit-mask-image: url(https://assets.codepen.io/77020/sw-jedi-crest.svg);
  -webkit-mask-size: 10%;
  -webkit-mask-position: center;
  -webkit-mask-repeat: no-repeat;
}

.scenes:is(:hover, :focus) .scene-2 {
  animation: scene-transition 4s cubic-bezier(1, 0, 1, 1) forwards;
}

20240815_110406.gif

    <div class="scenes" tabindex="0">
      <div class="scene-1">
        <h2 class="scene-title">Kylo Ren</h2>
      </div>
      <div class="scene-2">
        <h2 class="scene-title">C-3PO and Captain Gandalf</h2>
      </div>
    </div>


// css
@property --angle {
  syntax: '<angle>';
  inherits: true;
  initial-value: -10deg;
}

@keyframes scene-transition {
  to {
    --angle: 370deg;
  }
}

.scenes {
  position: relative;
  width: 500px;
  height: 300px;
  outline: 2px solid #ccc;
}

.scene-1,
.scene-2 {
  position: absolute;
  inset: 0;
  background-size: cover;
}

.scene-1 {
  background-image: url(https://img-s-msn-com.akamaized.net/tenant/amp/entityid/AA1oGYlS.img?w=768&h=783&m=6);
}

.scene-2 {
  background-image: url(https://img-s-msn-com.akamaized.net/tenant/amp/entityid/AA1oEjiP.img?w=768&h=480&m=6&x=394&y=103&s=381&d=381);
  z-index: -1;
  -webkit-mask-image:
    conic-gradient(#fff 0deg,
      #fff calc(var(--angle) - 10deg),
      transparent calc(var(--angle) + 10deg),
      transparent 360deg),
    conic-gradient(transparent 340deg,
      #fff 360deg);
}

.scenes:is(:hover, :focus) .scene-2 {
  z-index: 1;
  animation: scene-transition 2s linear forwards;
}

20240815_110911.gif

   <div class="scenes" tabindex="0">
      <div class="scene-1">
        <h2 class="scene-title">Kylo Ren</h2>
      </div>
      <div class="scene-2">
        <h2 class="scene-title">C-3PO and Captain Gandalf</h2>
      </div>
    </div>

 // css
@property --radius {
  syntax: '<percentage>';
  inherits: true;
  initial-value: -5%;
}

@keyframes scene-transition {
  to {
    --radius: 105%;
  }
}

.scenes {
  position: relative;
  width: 500px;
  height: 300px;
}

.scene-1,
.scene-2 {
  position: absolute;
  inset: 0;
  background-size: cover;
}

.scene-1 {
  background-image: url(https://img-s-msn-com.akamaized.net/tenant/amp/entityid/AA1oGYlS.img?w=768&h=783&m=6);
}

.scene-2 {
  background-image: url(https://img-s-msn-com.akamaized.net/tenant/amp/entityid/AA1oEjiP.img?w=768&h=480&m=6&x=394&y=103&s=381&d=381);
  -webkit-mask-image: radial-gradient(circle,
      #fff calc(var(--radius) - 5%),
      transparent calc(var(--radius) + 5%));
}

.scenes:is(:hover, :focus) .scene-2 {
  z-index: 1;
  animation: scene-transition 2s linear forwards;
}

20240815_111340.gif

 <div class="scenes" tabindex="0">
      <div class="scene-1">
        <h2 class="scene-title">Kylo Ren</h2>
      </div>
      <div class="scene-2">
        <h2 class="scene-title">C-3PO and Captain Gandalf</h2>
      </div>
 </div>
    
//css
.scenes {
  position: relative;
  width: 500px;
  height: 300px;
}

.scene-1,
.scene-2 {
  position: absolute;
  inset: 0;
  background-size: cover;
}

.scene-1 {
  background-image: url(https://img-s-msn-com.akamaized.net/tenant/amp/entityid/AA1oGYlS.img?w=768&h=783&m=6);
}

.scene-2 {
  background-image: url(https://img-s-msn-com.akamaized.net/tenant/amp/entityid/AA1oEjiP.img?w=768&h=480&m=6&x=394&y=103&s=381&d=381);
  -webkit-mask-image: linear-gradient(to right,
      transparent 47.5%,
      #fff 52.5%);
  -webkit-mask-size: 210%;
  -webkit-mask-position: left;
}

.scenes:is(:hover, :focus) .scene-2 {
  -webkit-mask-position: right;
  transition: -webkit-mask-position 2s linear;
}

打字机效果

20240724_165212.gif

<h1 style="text-shadow: 5px 5px 5px #000;">欢迎光临呐,各位访客们。</h1>

<style>
h1 {
    /* 本例12个文字(加标点符号);有多少个文字,width就是多少个em */
    width: 12em;
    /* 加上两个动画,一个是打字动画,使用steps让字一个一个的出现,
             注意step和字数保持一致,光标动画也是同理,*/
    animation: typingWords 5s steps(12) infinite, cursor 0.5s steps(1) infinite;
    /* 要设置不允许换行,且溢出隐藏 */
    white-space: nowrap;
    overflow: hidden;
    /* 使用右边框作为打印的指针光标 */
    border-right: 1px solid #000;
}
@keyframes typingWords {
    0% {
        width: 0;
    }
}

@keyframes cursor {
    50% {
        border-color: transparent;
    }
}
</style>

扩展卡

20240716_102025.gif

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Expanding Cards</title>
</head>

<body>
  <div class="container">
    <div class="panel active"
      style="background-image: url('https://images.unsplash.com/photo-1558979158-65a1eaa08691?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80')">
      <h3>Explore The World</h3>
    </div>
    <div class="panel"
      style="background-image: url('https://images.unsplash.com/photo-1572276596237-5db2c3e16c5d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80')">
      <h3>Wild Forest</h3>
    </div>
    <div class="panel"
      style="background-image: url('https://images.unsplash.com/photo-1507525428034-b723cf961d3e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1353&q=80')">
      <h3>Sunny Beach</h3>
    </div>
    <div class="panel"
      style="background-image: url('https://images.unsplash.com/photo-1551009175-8a68da93d5f9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1351&q=80')">
      <h3>City on Winter</h3>
    </div>
    <div class="panel"
      style="background-image: url('https://images.unsplash.com/photo-1549880338-65ddcdfd017b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80')">
      <h3>Mountains - Clouds</h3>
    </div>
  </div>
</body>

<style>
  @import url('https://fonts.googleapis.com/css?family=Muli&display=swap');

  * {
    box-sizing: border-box;
  }

  body {
    font-family: 'Muli', sans-serif;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100vh;
    overflow: hidden;
    margin: 0;
  }

  .container {
    display: flex;
    width: 90vw;
  }

  .panel {
    flex: 0.5;
    height: 80vh;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    border-radius: 50px;
    color: #fff;
    cursor: pointer;
    margin: 10px;
    position: relative;
    -webkit-transition: all 700ms ease-in;
  }

  .panel h3 {
    font-size: 24px;
    position: absolute;
    bottom: 20px;
    left: 20px;
    margin: 0;
    opacity: 0;
  }

  .panel.active {
    flex: 5;
  }

  .panel.active h3 {
    opacity: 1;
    transition: opacity 0.3s ease-in 0.4s;
  }

  @media (max-width: 480px) {
    .container {
      width: 100vw;
    }

    .panel:nth-of-type(4),
    .panel:nth-of-type(5) {
      display: none;
    }
  }
</style>

<script>
  const panels = document.querySelectorAll('.panel')

  panels.forEach((panel) => {
    panel.addEventListener('click', () => {
      removeActiveClasses()
      panel.classList.add('active')
    })
  })

  function removeActiveClasses() {
    panels.forEach((panel) => {
      panel.classList.remove('active')
    })
  }

</script>

</html>

隐藏的搜索小部件

20240716_103848.gif

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css" integrity="sha512-1PKOgIY59xJ8Co8+NE6FZ+LOAZKjy+KY8iq0G4B3CyeY6wYHN3yt9PW0XpSriVlkMXe40PTKnXrLnZ9+fkDaog==" crossorigin="anonymous" />
    <title>Hidden Search</title>
  </head>
  <body>
    <div class="search">
      <input type="text" class="input" placeholder="Search...">
      <button class="btn">
        <i class="fas fa-search"></i>
      </button>
    </div>
  </body>
  <style>
  @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');

  * {
    box-sizing: border-box;
  }

  body {
    background-image: linear-gradient(90deg, #7d5fff, #7158e2);
    font-family: 'Roboto', sans-serif;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100vh;
    overflow: hidden;
    margin: 0;
  }

  .search {
    position: relative;
    height: 50px;
  }

  .search .input {
    background-color: #fff;
    border: 0;
    font-size: 18px;
    padding: 15px;
    height: 50px;
    width: 50px;
    transition: width 0.3s ease;
  }

  .btn {
    background-color: #fff;
    border: 0;
    cursor: pointer;
    font-size: 24px;
    position: absolute;
    top: 0;
    left: 0;
    height: 50px;
    width: 50px;
    transition: transform 0.3s ease;
  }

  .btn:focus,
  .input:focus {
    outline: none;
  }

  .search.active .input {
    width: 200px;
  }

  .search.active .btn {
    transform: translateX(198px);
  }
</style>

<script>
  const search = document.querySelector('.search')
  const btn = document.querySelector('.btn')
  const input = document.querySelector('.input')

  btn.addEventListener('click', () => {
    search.classList.toggle('active')
    input.focus()
  })
</script>

</html>

滚动动画

20240716_111601.gif

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Scroll Animation</title>
</head>

<body>
  <h1>Scroll to see the animation</h1>
  <div class="box">
    <h2>Content</h2>
  </div>
  <div class="box">
    <h2>Content</h2>
  </div>
  <div class="box">
    <h2>Content</h2>
  </div>
  <div class="box">
    <h2>Content</h2>
  </div>
  <div class="box">
    <h2>Content</h2>
  </div>
  <div class="box">
    <h2>Content</h2>
  </div>
  <div class="box">
    <h2>Content</h2>
  </div>
  <div class="box">
    <h2>Content</h2>
  </div>
  <div class="box">
    <h2>Content</h2>
  </div>
  <div class="box">
    <h2>Content</h2>
  </div>
  <div class="box">
    <h2>Content</h2>
  </div>
  <div class="box">
    <h2>Content</h2>
  </div>
  <div class="box">
    <h2>Content</h2>
  </div>
</body>


<script>
  const boxes = document.querySelectorAll('.box')

  window.addEventListener('scroll', checkBoxes)

  checkBoxes()

  function checkBoxes() {
    const triggerBottom = (window.innerHeight / 5) * 4

    boxes.forEach((box) => {
      const boxTop = box.getBoundingClientRect().top

      if (boxTop < triggerBottom) {
        box.classList.add('show')
      } else {
        box.classList.remove('show')
      }
    })
  }

</script>
<style>
  @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');

  * {
    box-sizing: border-box;
  }

  body {
    background-color: #efedd6;
    font-family: 'Roboto', sans-serif;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    margin: 0;
    overflow-x: hidden;
  }

  h1 {
    margin: 10px;
  }

  .box {
    background-color: steelblue;
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 400px;
    height: 200px;
    margin: 10px;
    border-radius: 10px;
    box-shadow: 2px 4px 5px rgba(0, 0, 0, 0.3);
    transform: translateX(400%);
    transition: transform 0.4s ease;
  }

  .box:nth-of-type(even) {
    transform: translateX(-400%);
  }

  .box.show {
    transform: translateX(0);
  }

  .box h2 {
    font-size: 45px;
  }
</style>

</html>

以上是参考 GitHub - bradtraversy/50projects50days: 50+ mini web projects using HTML, CSS & JS