都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 去控制隐藏和显示了,这个大概以后会影响到很多组件库重写弹出层的逻辑。

相关推荐
李鸿耀2 分钟前
仅用几行 CSS,实现优雅的渐变边框效果
前端
码事漫谈22 分钟前
解决 Anki 启动器下载错误的完整指南
前端
im_AMBER41 分钟前
Web 开发 27
前端·javascript·笔记·后端·学习·web
蓝胖子的多啦A梦1 小时前
低版本Chrome导致弹框无法滚动的解决方案
前端·css·html·chrome浏览器·版本不同造成问题·弹框页面无法滚动
玩代码1 小时前
vue项目安装chromedriver超时解决办法
前端·javascript·vue.js
訾博ZiBo1 小时前
React 状态管理中的循环更新陷阱与解决方案
前端
StarPrayers.2 小时前
旅行商问题(TSP)(2)(heuristics.py)(TSP 的两种贪心启发式算法实现)
前端·人工智能·python·算法·pycharm·启发式算法
一壶浊酒..2 小时前
ajax局部更新
前端·ajax·okhttp
DoraBigHead3 小时前
React 架构重生记:从递归地狱到时间切片
前端·javascript·react.js
ะัี潪ิื3 小时前
精灵图(雪碧图)的生成和使用
java·css