都2024了,别拿IE当借口了,快去学这些css 新属性!!

前言

记得刚入行前端的时候,当时因为刚好学过 vmin vmax ,就直接在我们的移动端项目中用,结果被老大喷,说你写项目能不能别搞这些花里胡哨的,就用点朴实无华的行不行,我当时心里是 :*********

最近接手了一个项目,有一个 4乘4 的网格布局,我用了flex 去布局,然后又被同事嘲讽,都什么年代了, 这种布局明显是用 grid 更好啊,我当时心里是: ************

好好好!!! 好坏赖话都让你们说了是吧!!

言归正传,毕竟都 2024 年了 该学点新的 css 属性了,要不然过几年这些属性通用了你都没听说过。

@scope

你写了这么长时间项目 ,对于css 样式隔离应该不陌生, 比如Vue Scoped Styles react 中的 css in js 或者是 CSS Modules ,但是原生css 样式隔离方案应该没接触过吧 ,@scope 就是原生css 的样式隔离方案。

@scope 语法规则

css 复制代码
@scope (scope root) to (scope limit) {
  rulesets
}

大家可以自行去 MDNcsswg 去查看详细规则,他的主要用法有三种:

用法一

只用 第一个参数

html代码:

html 复制代码
<div class="box">
   <div class="red">这里是红色</div>
</div>
<div class="red">这里不是红色</div>

css代码:

css 复制代码
 <style>
      @scope (.box) {
        .red {
          background-color: red;
        }
      }
 </style>

运行结果:

我们可以看到, 类名为 .red 的只有在 scope 中才会显示为红色,说明样式隔离成功了

用法二

可以看到 还有个 to 包裹的类名,那他的含义是什么呢?

HTML代码

html 复制代码
 <div class="box">
      <div class="red">这里是红色</div>
      <div class="filter">
        <div class="red">这里不是红色,因为被过滤了</div>
        <div class="red-box">
          <div class="red">即使是子组件也不是红色,因为被过滤了</div>
        </div>
      </div>
      <div class="red">这里是红色</div>
    </div>
 <div class="red">这里不是红色</div>

css代码

css 复制代码
    <style>
      @scope (.box) to (.filter) {
        .red {
          background-color: red;
        }
      }
    </style>

运行结果

可以看到 to中的 .filter 下的所有的red 也不是红色 其实就是一种过滤效果,你也可以理解为这是一种甜甜圈的结构 只有.box 中和 .filter 以外的元素才能被选中 。

要注意 @scope 的用法是 @scope(空格)(元素类名)(空格)to(空格)(元素类名) to 后面的空格不要忘记了否则是不生效的

用法三

什么参数都不加 @sope

html 复制代码
    <div class="box">
      <style>
        @scope {
          .red {
            background-color: red;
          }
        }
      </style>
      <div class="red">这里是红色</div>
    </div>
    <div class="red">这里不是红色</div>

运行结果

作为包含在 HTML 元素中的内联样式,在这种情况下,前奏将被省略,并且包含的规则集会自动将范围限定为 元素 的封闭父元素 ,意思就是你写在了 html 结构中你就可以把 scope root给省略了,当然你加上也是没问题的。

@container 容器查询

这个设计几乎可以改变我们对"响应式设计"含义的看法,以前我们都是使用 @media 媒体查询 通过viewport 来调整样式的,但是这种太过于宏观,现在出了 @container 你可以根据父容器大小来设置元素的样式。

html 复制代码
 <style>
      .demo {
        width: 200px;
        height: 200px;
        background: red;
        container-name: sidebar;
        container-type: inline-size;
      }

      @container sidebar (width > 300px) {
        a {
          background: green;
        }
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div class="demo">
        <a>我的背景色会随着demo元素的宽度而变化</a>
      </div>
    </div>
  </body>

主要的用法就是 @container container-name (条件) { 样式表 }

你可以给需要增加容器查询的元素增加 container-namecontainer-type 如果你的全局只有一个@container 那你就可以 省略container-name ,对于container-type 总共有以下几个属性:

  • normal是默认值,表示不建立容器元素,

  • size表示水平和垂直方向都建立,

  • inline-size是只在水平方向建立,会给元素同时应用

  • layout、style和inline-size容器状态。

    最后 container-namecontainer-type 还可以简写成 container:sidebar /inline-size,

    具体使用可以查看 MDN

:has :where :is

:has 伪类选择器 --选中父级

在css 中,我们正常想选择某些东西 我们基本上是用后代选择器

css 复制代码
div p{ clolor:red }

但是我们有时候想 从子选中父,就可以用:has

css 复制代码
div:has(p){ color:red }

上面的意思表示将所有的含有p 标签的div 标签的颜色变成红色

应用场景:

我们公司就有位同事 二次封装了 form 表单 但是对于插槽功能会有段这个结构

你说我要选中 这个没有类名的div 我该如何选中 ,而且他还是封装起来的div 我无法动态给这个div加类名

有的人就说了 你可以用 .elform-item_content>div 啊 ,可是这样的话所有的这种结构都会被选中,但是我想要的是只有 含有 .chooseReviewIptr类名的才能被选中。

所以我们就可以这么写:

css 复制代码
 :deep(.el-form-item__content) div:has(.chooseReviewIpt) {
    width: 100%;
  }

当然 :has 还有其他很多种用法,他的出现确实惊艳了众人, MDN

:where伪类选择器 -- 匹配规则

平时你可能会写出这种代码

css 复制代码
header a:hover,
main a:hover,
footer a:hover {
  color: green;
  text-decoration: underline;
}

但是我们用了:where 就可以精简代码

css 复制代码
:where(header, main, footer) a:hover {
  color: red;
  text-decoration: underline;
}

这个伪类代表:选择所有能被该选择器列表中任何一条规则选中的元素 MDN

:is伪类选择器 -- 匹配规则

:is 用法和 :where 运行方式几乎一样 主要的区别在于 :where 优先级总为 0 ,:is的优先级取决于最特定参数的优先级 MDN

css嵌套

sass 、less 嵌套 大家应该都很熟悉了,css 嵌套目前浏览器也是支持了的

使用方法:

html 复制代码
    <div class="box">
      <div class="red">这里是红色</div>
      <span>红色</span>
    </div>
    <div class="red">这里不是红色</div>
css 复制代码
      div {
        color: red;
        span {
          color: green;
        }
      }
css 复制代码
      .box {
        .red {
          color: red;
        }
      }
css 复制代码
      .box {
        & .red {
          color: red;
        }
      }

注意点

但是你得注意到 原生css 嵌套 和sass less 的嵌套规则还是有所区别的

css 复制代码
.card {
  &--header {
    /* is not equal to ".card--header" */
  }
}

在css 中是不支持这种写法的 ,他会被会忽略掉 ,但是在sass 中是可以的,不过后续css官方会不会支持这种写法还不太清楚

nth-of

如果给你一下需求,你会怎么去实现 ?

下面是一个不可以更改的结构 比如从一个被封装的组件 你无法修改他的结构也不能动态加类名,你改如何用css去选中 第二个类名为.p2 的标签

html 复制代码
    <h1 class="h1">标题1</h1>
    <h1 class="h2">标题2</h1>
    <p class="p1">段落1</p>
    <p class="p1">段落1</p>
    <p class="p2">段落2</p>
    <p class="p2">段落2</p>  选中这个
    <p class="p2">段落2</p>
    <p class="p3">段落3</p>

你可能会第一反应 是nth-child 和 nth-of-type,那我们来讨论下:

1、nth-child

css 复制代码
.p2:nth-child(2){
    color:red
}

你会发现根本选不中 因为上面这个选择器的含义是==>父级下:nth-child(2) 第二个子元素 并且类名为.p2的元素

所以这样是选不中的。

2、:nth-of-type

css 复制代码
.p2:nth-of-type(2){
    color:red
}

这种也是选不中的,因为 上面的含义是:

​ 1)父级下 :nth-of-type(2) 每种类型的第二个元素 并且类名为.p2的才能被选中,

​ 2)也就是说父级下总共有h1 、p 两种元素 ,

​ 3)h1元素 的第二个就是 标题2 , p 元素的第二个就是 第二个段落一 ,

​ 4) 被选中的就是这两个元素的类名分别为 .h2 和 .p1 ,不符合 类名为.p2 的条件所以不被选中

​ 放在以前我们是很不好通过css 去选中这个结构的 我们八成会通过 js 去选中 不过现在出现了 of 关键词了, 可以很好解决我们这个问题。

3、nth-child 中的 of 关键词

你就可以这么写

css 复制代码
:nth-child(2 of .p2){
  color: red
}

上面的意思就是

​ 1)首先筛选 父级下所有的类名为 .p2的

​ 2)然后在这个筛选结果中 选择第二个

这样就很轻松的选中我们需要选中的了。

text-wrap: 新增的两个属性 balance 与 pretty

text-wrap: balance

平时我们开发过程中 很可能会遇到这种情况

一行文字放不下 会折行,会给用户一种错觉 coffee 是突出的效果,但是从UI的角度更想要的是这种效果:

我们之前大多都是两种解决方案 一种是在 every 后面加个 <br>换行,或者是用两个p 标签分割这个结构 导致他们不在同一行。

但是我们可以感受到这种都是去通过打断句子的方式,所以官方就出了新的属性text-wrap:balance

加了这个属性之后浏览器会自动计算单词的数量,并将他们平分在两行

pretty

也有可能你想要的不是均分单词 仅仅是不想让最后一行出现单独的单词,这个时候你就可以用text-wap:blance的方式 ,他就会让最后一行多几个单词显示。

原生的popover弹出层

很多时候我们是不是都会遇到有 弹出层popover的需求,大多时候我们要么用组件库中的要么自己手写,现在你不需要了,因为浏览器已经支持原生popover了

html 复制代码
    
<button class="menu-btn" popovertarget="menu">
      <img src="https://upload.wikimedia.org/wikipedia/commons/b/b2/Hamburger_icon.svg" alt="" />
    </button>
    <div popover role="menu" id="menu">
      <button class="close-btn" popovertarget="menu" popovertargetaction="hide">
        <span>❌</span>
        <span class="sr-only">Close</span>
      </button>
      <ul>
        <li><a href="#">Typography</a></li>
        <li><a href="#">Foundations</a></li>
        <li><a href="#">Color</a></li>
        <li><a href="#">Interactions</a></li>
        <li><a href="#">Components</a></li>
        <li><a href="#">Responsive</a></li>
      </ul>
    </div>

用法就是 你得给需要做弹框的容器增加 popover 属性 并且增加id 属性 后使用 popovertarget="my-popover" 将其 id 属性与调用按钮相关联。这会让我们更加轻松的实现弹出层,不用去写js 去控制隐藏和显示了,这个大概以后会影响到很多组件库重写弹出层的逻辑。

相关推荐
神仙别闹10 分钟前
基于tensorflow和flask的本地图片库web图片搜索引擎
前端·flask·tensorflow
GIS程序媛—椰子1 小时前
【Vue 全家桶】7、Vue UI组件库(更新中)
前端·vue.js
DogEgg_0011 小时前
前端八股文(一)HTML 持续更新中。。。
前端·html
ZL不懂前端1 小时前
Content Security Policy (CSP)
前端·javascript·面试
木舟10091 小时前
ffmpeg重复回听音频流,时长叠加问题
前端
王大锤43911 小时前
golang通用后台管理系统07(后台与若依前端对接)
开发语言·前端·golang
我血条子呢2 小时前
[Vue]防止路由重复跳转
前端·javascript·vue.js
黎金安2 小时前
前端第二次作业
前端·css·css3
啦啦右一2 小时前
前端 | MYTED单篇TED词汇学习功能优化
前端·学习