阅读视图

发现新文章,点击刷新页面。

CSS Grid 案例

CSS Grid 案例详解

1、min-content、max-content、auto 空间计算

单列 auto 布局:内容宽度决定列宽,剩余空间自动分配

auto-1.png

双列 auto 布局:两列宽度根据内容自动调整

auto-2.png

三列 auto 布局:多列布局时内容宽度的分配方式

auto-3.png

四列 auto 布局:列数增加时的空间分配逻辑

auto-4.png

max-content:列宽等于内容最大宽度,不换行

max-content.png

min-content:列宽等于内容最小宽度,尽可能换行

min-content.png

min-content 最小宽度,max-content 完整内容宽度, auto 自动分配剩余空间 列宽等于内容最小宽度,尽可能换行

<body>
    <div class="grid">
        <div class="item">内容1</div>
        <div class="item">内容2</div>
        <div class="item">内容3</div>
        <div class="item">内容4</div>
    </div>
</body>
<style>
    .grid {
        display: grid;
        /*  左(自动分配剩余)
            右(内容最大或最小) */
        grid-template-columns: auto max-content;
        
        /* 单列,两列,三列,四列 */
        grid-template-columns: auto;
        grid-template-columns: auto auto;
        grid-template-columns: auto auto auto;
        grid-template-columns: auto auto auto auto;
        grid-template-columns: auto min-content;

        /* 加间距,方便看列的边界 */
        grid-column-gap: 5px;
        grid-row-gap: 5px;
        background-color: #c1c1c1;
        padding: 5px;
    }

    .item {
        /* 加背景,直观区分列 */
        border: 1px solid #000;
        padding: 2px;
    }
</style>

<!-- 
★ auto 特性:优先适应父容器宽度,剩余空间自动分配,内容超出时会换行
★ max-content:列宽=内容不换行时的最大宽度(内容不会折行)
★ min-content:列宽=内容能折行时的最小宽度(内容尽可能折行收缩)
★ 多列 auto:列数=auto的个数,列宽优先适配自身内容,剩余空间平分 
-->

2、space-between

2、stretch 内容填充.png

两个内容自动撑开, 左右排列
<div class="container">
    <div class="item">用户123</div>
    <div class="item">很多内容</div>

    <div class="item">内容</div>
    <div class="item">很多内容很多内容</div>
</div>

<style>
    .container {
        width: 300px;
        display: grid;
        grid-template-columns: auto auto;
        /** 两个内容自动撑开, 左右排列 **/
        justify-content: space-between;
        background-color: blueviolet;
    }

    .item {
        background-color: skyblue;
    }
</style>

3、auto-fit、minmax 填满剩余空间

单列布局,当容器宽度不足时自动调整为单列

3、一列.png

两列布局:容器宽度足够时自动扩展为多列

3、两列.png

三列布局:自适应容器宽度的多列排列

3、三列.png

四列布局:充分利用可用空间的自适应布局

3、铺满四列.png

<main>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
</main>

<style>
    main {
        display: grid;
        grid-gap: 5px;
        /* 1、minmax 定义尺寸范围 */

        /* 2、
              auto-fill 在宽度足够的条件下预留了空白
              auto-fit 在宽度足够的条件下充分利用空间
              */
        grid-template-columns: repeat(auto-fit, minmax(600px, 1fr));
        border: 3px dashed;
    }

    div {
        background-color: deepskyblue;
        height: 100px;
    }
</style>

4、grid 命名格子

使用grid-template-areas,通过命名区域实现复杂的网格布局

4、grid 命名格子.png

代码

<div class="container">
    <div class="item putao">葡萄</div>
    <div class="item longxia">龙虾</div>
    <div class="item yangyu">养鱼</div>
    <div class="item xigua">西瓜</div>
</div>

<style>
    .container {
        height: 400px;
        display: grid;
        /* grid-template-columns: repeat(3, 1fr);
        grid-template-rows: repeat(4, 1fr);
        grid-template-areas:
            "葡萄 葡萄 葡萄"
            "龙虾 养鱼 养鱼"
            "龙虾 养鱼 养鱼"
            "西瓜 西瓜 西瓜"
        ; */
        /* 简写 */
        grid: "葡萄 葡萄 葡萄" 1fr "龙虾 养鱼 养鱼" 1fr "龙虾 养鱼 养鱼" 1fr "西瓜 西瓜 西瓜" 1fr / 1fr 1fr 1fr;
    }

    .putao {
        grid-area: 葡萄;
        background-color: greenyellow;
    }

    .longxia {
        grid-area: 龙虾;
        background-color: plum;
    }

    .yangyu {
        grid-area: 养鱼;
        background-color: slategray;
    }

    .xigua {
        grid-area: 西瓜;
        background-color: crimson;
    }

    .container .item {
        display: flex;
        align-items: center;
        justify-content: center;
    }
</style>

5、隐形网格

image.png 隐式网格: 超出显式网格范围的项目自动创建新行

代码

<div class="container">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item">5隐式网格</div>
</div>
<style>
    .container {
        display: grid;
        grid: 1fr 1fr/1fr 1fr;
        grid-auto-rows: 100px;
    }

    .item:nth-of-type(1) {
        background-color: rgb(239, 255, 170);
    }

    .item:nth-of-type(2) {
        background-color: rgb(182, 184, 255);
    }

    .item:nth-of-type(3) {
        background-color: rgb(255, 195, 253);
    }

    .item:nth-of-type(4) {
        background-color: rgb(210, 255, 179);
    }

    .item:nth-of-type(5) {
        background-color: rgb(185, 185, 185);
    }
</style>

6、隐式网格2

隐式网格的列布局: grid-auto-columns设置隐式列的宽度

image.png

<div class="container2">
    <div class="item-a">a</div>
    <div class="item-b">b</div>
</div>
<style>
    .container2 {
        display: grid;
        grid-template: 1fr 1fr/1fr 1fr;
        /* 额外列(第 3 列 +)宽度固定 60px; */
        grid-auto-columns: 60px;
        border: 1px solid #000;
    }

    .item-b {
        /* 让 item-b 占第 3 列(第 3-4 根列线之间) */
        grid-column: 3/4;
        background-color: aqua;
    }
</style>

7、grid-auto-flow 流向

默认row 流向: 左到右、从上到下排列

7、grid-auot-flow 流向.png

column流向: 上到下、从左到右排列

7、grid-auto-flow 流向2.png

<div class="container">
    <div class="item">格子1</div>
    <div class="item">格子2</div>
    <div class="item">格子3</div>
    <div class="item">格子4</div>
    <div class="item">格子5</div>
    <div class="item">格子6</div>
    <div class="item">格子7</div>
    <div class="item">格子8</div>
    <div class="item">格子9</div>
</div>
<style>
    .container{
        display: grid;
        line-height: 40px;
        background-color: skyblue;
        
        /* 默认流向是左往右,再下一行左往右,重复前面方式 */
        grid-template-columns: 1fr 1fr;
        grid-auto-flow: row;

        /* 换一个方向,上往下 */
        /* grid-template-rows: 1fr 1fr;
        grid-auto-flow: column; */
    }
    .item{
        outline: 1px dotted;
    }
</style>

8、grid-auto-flow 图片案例

第一个图片占据两行空间,其他图片自动排列

image.png
<div class="container">
    <div class="item"><img src="./图片/shu.webp"></div>
    <div class="item"><img src="./图片/1.webp"></div>
    <div class="item"><img src="./图片/2.webp"></div>
    <div class="item"><img src="./图片/3.webp"></div>
    <div class="item"><img src="./图片/4.webp"></div>
 
</div>
<style>
 .container {
    display: grid;
    background-color: skyblue;
 
    /* 1. 修复:去掉 grid-auto-flow: column,用默认 row 按行排列 */
    /* 2. 修复:用 minmax(0, 1fr) 防止单元格被图片撑大 */

    grid-template: 
        "a . ." minmax(0, 1fr)
        "a . ." minmax(0, 1fr)
        / minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr);
    grid-gap: 6px;
    
}

/* 第一个元素占网格区域 a(2行1列) */
.container .item:first-child {
    grid-area: a;
}

/* 修复:图片不溢出、不变形 */
.container img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover; /* 按比例裁剪,填满单元格 */
}
</style>

9、dense 填补

dense填补: 自动填补空缺位置,优化空间利用 image.png

<div class="container">
    <div class="item">各自1</div>
    <div class="item">各自2</div>
    <div class="item">各自3</div>
    <div class="item">各自4</div>
    <div class="item">各自5</div>
    <div class="item">各自6</div>
    <div class="item">各自7</div>
    <div class="item">各自8</div>
    <div class="item">各自9</div>
</div>

<style>
    .container {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        grid-auto-flow: dense;
    }

    .container .item {
        outline: 1px dotted;
    }

    /* 模拟空缺位置 */
    .container .item:first-child {
        grid-column-start: 2;
    }
</style>

10、grid 简写

<style>

    /*
       1、 none 表示设置所有子项属性值为初始化值
        grid:none

       2、template 
        单独:
        grid-template-rows:100px 300px;
        grid-template-columns:3fr 1fr;

        简写:
        grid:100px 300px / 3fr 1fr;
        
        4、auto-flow 
        单独 
        grid-template-rows: 100px 300px;
        grid-auto-flow: column;
        grid-auto-columns: 200px; 

         合并
        grid: 100px 300px / auto-flow 200px;

      3、template-areas
      完整:
       grid-template-columns: repeat(3, 1fr);
       grid-template-rows: repeat(4, 1fr);
       grid-template-areas:
            "葡萄 葡萄 葡萄"
            "龙虾 养鱼 养鱼"
            "龙虾 养鱼 养鱼"
            "西瓜 西瓜 西瓜"; 

        简写:
        grid: 
         "葡萄 葡萄 葡萄" 1fr
         "龙虾 养鱼 养鱼" 1fr 
         "龙虾 养鱼 养鱼" 1fr 
         "西瓜 西瓜 西瓜" 1fr 
         / 1fr 1fr 1fr;
    */
</style>

11、place-items 完整写法

image.png

place-items:项目在单元格内的居中对齐方式

<div class="container">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
</div>

<style>
    .container {
        display: grid;
        grid: 1fr 1fr/1fr 1fr;
        height: 300px;
        background-color: skyblue;

        /* 单个,类似flex  
        
        justify-content: center;
        align-items: center;
        
        */

        /* 合并 */
        place-items: center right;
    }
    .item{
        outline: 1px solid;
    }
 
</style>

12、layout栏布局

经典的页面布局: 包含头部、侧边栏、主内容和底部四个区域 image.png

<style>
    .grid-container {
      width: 500px;
      height: 400px;
      margin: 20px auto;
      display: grid;
      /* 精简核心:去掉重复线名,换行简化,保留关键命名 */
      grid-template:
        [r1] "header header header" 1fr [r2]
        [r2] "sidebar main main"    2fr [r3]
        [r3] "sidebar footer footer" 1fr [r4]
        / [c1] 150px [c2] 1fr [c3] 1fr [c4];   
      gap: 8px;
    }

    /* 子项定位(极简写法) */
    .grid-container>div{display: flex;justify-content: center;align-items: center;}
    .header { grid-area: header; background: #409eff; color: #fff;  }
    .sidebar { grid-row: r2/r4; grid-column: c1/c2; background: #67c23a; color: #fff;  }
    .main { grid-area: main; background: #e6a23c; color: #fff;  }
    .footer { grid-row: r3/r4; grid-column: c2/c4; background: #f56c6c; color: #fff;  }
  </style>

<body>
  <div class="grid-container">
    <div class="header">头部</div>
    <div class="sidebar">侧边栏</div>
    <div class="main">主内容</div>
    <div class="footer">底部</div>
  </div>
</body>
<!-- Grid 布局示例,含命名网格线 + 区域命名,3 行 3 列分头部 / 侧边 / 主内容 / 底部 -->

13、grid-area 线条版

image.png grid重叠: 图片和标题在同一网格单元格内叠加

<figure>
    <img src="./图片/13.png">
    <figcaption>自然风景</figcaption>
</figure>

<style>
    figure {

        display: grid;
    }

    img {
        width: 100%;
    }

    figure>img,
    figure>figcaption {
        grid-area: 1 / 1 / 2 / 2;
    }

    figure>figcaption {
        align-self: end;
        text-align: center;
        background: #0009;
        color: #fff;
        line-height: 2;
    }
</style>

附录

参考资源

  • 《CSS新世界》- 张鑫旭

html与CSS伪类技巧

CSS选择器文档

本文档基于15个HTML示例文件介绍了CSS的各种技巧实践,旨在记录开发时候CSS的场景应用。

  1. 影子DOM样式隔离
  2. :not()伪类简化代码
  3. :is()伪类简化选择器
  4. :active伪类实现埋点统计
  5. :focus-within实现搜索交互
  6. <small>标签的使用
  7. <details><summary>实现折叠面板
  8. :placeholder-shown实现输入提示
  9. :default伪类标记默认选项
  10. <label>交互与计数器
  11. 表单校验与反馈
  12. <fieldset><legend>组织表单
  13. :empty伪类处理空内容
  14. :only-child伪类条件显示
  15. :not()伪类初始化样式

1. 影子DOM样式隔离

使用attachShadow()方法创建影子DOM,实现组件的样式隔离,避免样式冲突。

<body>
   <p>外部文字,颜色为黑色</p>
   <div id="hostElement"></div>
</body>

<script>
   const hostElement = document.querySelector('#hostElement')
   const shadow = hostElement.attachShadow({ mode: 'open' })
   shadow.innerHTML = `<p>可以实现组件的样式隔离,颜色为红色</p>`
   shadow.innerHTML += `<style>p{color:red}</style>`
</script>
  • 组件开发,特别是自定义元素
  • 第三方插件集成
  • 样式封装和隔离

2. :not()伪类简化代码

使用:not()伪类排除特定元素,简化CSS选择器,避免重复样式定义。

<ul>
      <li>列表1</li>
      <li>列表2</li>
      <li>列表3</li>
</ul>

<style>
    /*列表最后一项排除*/
    li:not(:last-child){
        border-bottom: 1px solid black;
        padding-bottom:8px;
        margin-bottom: 8px;
    }
</style>
  • 列表项样式处理(如最后一项无边框)
  • 导航菜单样式
  • 表单元素样式排除

3. :is()伪类简化选择器

使用:is()伪类将多个选择器组合成一个,简化CSS代码结构,提高可读性。

<body>
    <header> <a href='#'> 头部字体 </a>  </header>
    <main> <a href='#'> 主题字体 </a>  </main>
    <footer> <a href='#'> 底部字体 </a> </footer>
</body>

<style>
   /* 常见嵌套写法,需经过编译
    header,main,footer{  
       a{   color: red;   } 
    } 
   编译过后 
   header a,main a,footer a{  color: red  } 
   */

    /* :is() 是原生 CSS 语法,无需编译,浏览器直接识别 */
    :is(header, main, footer) a  {   color: red   }
</style>
  • 多个容器内相同元素的样式统一
  • 复杂选择器的简化

4. :active伪类实现埋点统计

使用:active伪类结合content属性,实现无JavaScript的埋点统计功能。

<body>
    <button class="button1">点我上传</button>
    <button class="button2">点我上传2</button>
</body>

<style>
    /* 第一次点击可以触发 */
.button1:active::after{
    content: url(./pixxel.gif?action=click&id=button1);
}
.button2:active::after{
    content: url(./pixxel.gif?action=click&id=button2);
}
</style>
  • 简单的用户行为统计
  • 按钮点击事件追踪
  • 无需JavaScript的埋点方案

5. :focus-within实现搜索交互

使用:focus-within伪类实现父元素在子元素获得焦点时的样式变化,适用于搜索框下拉菜单等交互场景。

<!-- 适合做 搜索框结果的 下拉 -->
<div class="cs-details">
    <a href="javascript:" class="cs-summary">我的消息</a>
    <div class="cs-datalist">
        <a href>我的回答<sup>12</sup></a>
        <a href>我的私信</a>
        <a href>未评价订单</a>
        <a href>我的关注</a>
    </div>
</div>


<style>
    .cs-datalist {
        display: none;
        position: absolute;
        border: 1px solid #000;
        background-color: #fff;
    }

    .cs-details:focus-within .cs-datalist {
        display: block;
    }
</style>
  • 搜索框下拉菜单
  • 导航菜单的子菜单显示
  • 表单元素的关联信息展示

6. <small>标签的使用

使用<small>标签表示小号文本,通常用于免责声明、注释等次要信息。

<small>你好</small>
<div>你好123</div>
  • 法律声明和条款
  • 文章注释和说明
  • 表单字段的辅助信息

7. <details><summary>实现折叠面板

使用<details><summary>标签实现原生的折叠面板功能,无需JavaScript。

<details style="user-select:none;">
    <summary>请选择</summary>
    <ul>
        <li>选项1</li>
        <li>选项2</li>
        <li>选项3</li>
    </ul> 
</details>  
  • 常见问题解答(FAQ)
  • 内容折叠展示
  • 配置选项面板

8. :placeholder-shown实现输入提示

使用:placeholder-shown伪类检测输入框是否显示占位符,实现输入状态的样式变化。

<input type="search" placeholder="请输入内容">
<small>尚未输入内容</small>

<style>
    :not(:placeholder-shown)+small {
        color: transparent;
    }
</style>
  • 输入框的状态提示
  • 表单验证的视觉反馈
  • 提升用户输入体验

9. :default伪类标记默认选项

使用:default伪类标记表单中的默认选项,如默认选中的单选按钮。

<!-- 更换选择,自动补充(推荐) -->
<p>请选择支付方式:</p>
<p><input name="pay" type="radio"><label>支付宝</label></p>
<p><input name="pay" type="radio" checked><label>微信</label></p>
<p><input name="pay" type="radio"><label>银行卡</label></p>

<style>
    input:default+label::after {
        content: '(推荐)';
    }
</style>
  • 表单默认选项标记
  • 推荐选项提示
  • 提高用户表单填写效率

10. <label>交互与计数器

使用<label>标签与复选框关联,结合CSS计数器实现选中项数量统计。

<body>
    <p>请选择你感兴趣的话题:</p>

    <input type="checkbox" id="topic1">
    <label for="topic1" class="cs-topic">科技</label>

    <input type="checkbox" id="topic2">
    <label for="topic2" class="cs-topic">体育</label>

    <input type="checkbox" id="topic3">
    <label for="topic3" class="cs-topic">军事</label>

    <input type="checkbox" id="topic4">
    <label for="topic4" class="cs-topic">娱乐</label>

    <p>您已选择 <span class="cs-topic-counter"></span>个话题。</p>

</body>

<style>
    .cs-topic {
        padding:5px 15px;
        cursor: pointer;
        border: 1px solid #000;
    }
    :checked+.cs-topic {
        border-color: skyblue;
        background-color: azure;
    }
    [type='checkbox'] {
        position: absolute;
        clip: rect(0 0 0 0);
    }

    body {
        counter-reset: topicCounter;
    }

    :checked+.cs-topic {
        counter-increment: topicCounter;
    }

    .cs-topic-counter::before {
        content: counter(topicCounter);
    }
</style>
  • 兴趣标签选择
  • 商品属性选择
  • 多选项表单交互

11. 表单校验与反馈

使用CSS伪类实现表单验证的视觉反馈,包括输入合法、非法和空值状态。

<!-- 表单校验 -->

<form id="csForm" novalidate>
    <p>
        验证码:
        <input class="cs-input" required pattern="\w{4}" placeholder="">
        <span class="cs-vaild-tips"></span>
    </p>

    <input type="submit" />
</form>

<style>
    /* 校验通过 */
    .cs-input:valid {
        background-color: green;
        color: #fff;
    }
    .valid .cs-input:valid+.cs-vaild-tips::before {
        content: '√';
        color: green;
    }

    /* 校验不合法提示 */
    .valid .cs-input:not(:placeholder-shown):invalid {
        border: 2px solid red;
    }
    .valid .cs-input:not(:placeholder-shown):invalid+.cs-vaild-tips::before {
        content: '不符合要求';
        color: red;
    }

    /* 空值提示 */
    .valid .cs-input:placeholder-shown+.cs-vaild-tips::before {
        content: '尚未输入值';
    }
</style>

<script>
    const form = document.querySelector('#csForm')
    const input = document.querySelector('.cs-input')

    // 即时的校验
    // form.addEventListener('input',(e)=>{
    //     form.classList.add('valid')
    // })

    // 优化:输入时实时更新校验提示(可选,提升体验)
    input.addEventListener('input', () => {
        if (form.classList.contains('valid')) {
            // 强制重绘,更新样式
            void form.offsetWidth;
        }
    })

    form.addEventListener('submit', (e) => {
        e.preventDefault()
        form.classList.add('valid') // 触发校验样式

        if (form.checkValidity()) {
            alert('校验通过')
        }
    })
</script>
  • 表单验证反馈
  • 实时输入校验
  • 提升表单填写体验

12. <fieldset><legend>组织表单

使用<fieldset><legend>标签组织表单内容,提高表单的结构性。

<form>
    <fieldset>
        <legend>问卷调查</legend>
        <ol>
            <li>1-3年</li>
            <li>3-5年</li>
            <li>5年以上</li>
            <h4>你从事前端几年了?</h4>
        </ol>
    </fieldset>
</form>
  • 复杂表单的分组
  • 提高表单的可访问性
  • 增强表单的语义结构

13. :empty伪类处理空内容

使用:empty伪类检测元素是否为空,为空白元素添加默认内容或样式。

<dl>
    <dt>姓名:</dt>   <dd>张三</dd>
    <dt>性别:</dt>   <dd></dd>
    <dt>手机:</dt>   <dd></dd>
    <dt>邮箱:</dt>   <dd></dd>
</dl>

<!-- :empty 兼容 ''、null,配合伪元素可填充自定义内容 -->
<style>
    dt {   float: left    }

    dd:empty::before {
        color: gray;
        /* content: '-'; */
        content: '暂无';
    }
</style>
  • 数据展示中的空值处理
  • 搜索结果为空的提示
  • 表单字段的默认显示

14. :only-child伪类条件显示

使用:only-child伪类检测元素是否为唯一子元素,实现条件性的样式显示。

<ul>
    <li> 仅剩一项时不可删除 <button>删除</button> </li>
    <li> 仅剩一项时不可删除 <button>删除</button> </li>
    <li> 仅剩一项时不可删除 <button>删除</button> </li>
</ul>

<style>
    li:only-child button { display: none  }
</style>


<script>
    // 点击删除 li
    const buttons = document.querySelectorAll('li button')
    buttons.forEach(btn => {
        btn.addEventListener('click', function () {
            btn.parentElement.remove()
        })
    })
</script>
  • 列表项的删除按钮控制
  • 条件性UI元素显示
  • 动态内容的样式调整

15. :not()伪类初始化样式

使用:not()伪类排除特定元素,实现样式的初始化和重置。

<!-- 激活面板优雅切换 -->
<!-- 
<div class="cs-panel">面板1</div>
<div class="cs-panel active">面板2</div>
<div class="cs-panel">面板3</div>

<style>  .cs-panel:not(.active) { display: none} </style>
 -->


<!-- 灵活性 -->
<div class="cs-panel">面板1</div>
<div class="cs-panel  flex">面板2</div>
<div class="cs-panel active grid">面板3</div>

<style>
    .cs-panel:not(.active) {  display: none  }
    
    .flex {    display: flex  }
    .grid {    display: grid   }
</style>
  • 选项卡面板切换
  • 激活状态的样式控制
  • 组件的默认状态管理

总结

本文档介绍了CSS新世界中的15个实用技巧,涵盖了样式隔离、选择器优化、表单交互、内容展示等多个方面。这些技巧充分利用了现代CSS的新特性,能够帮助开发者编写更简洁、高效、可维护的代码,同时提升用户体验。

随着CSS标准的不断发展,我们可以期待更多强大的特性和技巧出现。希望本文档能够为开发者提供参考,让大家在CSS的世界中探索更多可能性。

参考资源

  • 张鑫旭《css选择器》
❌