惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
爱范儿
爱范儿
H
Help Net Security
V
Visual Studio Blog
J
Java Code Geeks
Stack Overflow Blog
Stack Overflow Blog
Microsoft Security Blog
Microsoft Security Blog
Apple Machine Learning Research
Apple Machine Learning Research
MyScale Blog
MyScale Blog
The Cloudflare Blog
Martin Fowler
Martin Fowler
D
Docker
腾讯CDC
F
Fortinet All Blogs
雷峰网
雷峰网
GbyAI
GbyAI
G
Google Developers Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Recent Announcements
Recent Announcements
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Blog — PlanetScale
Blog — PlanetScale
Engineering at Meta
Engineering at Meta
博客园 - 聂微东
博客园 - 叶小钗

张鑫旭-鑫空间-鑫生活

1分钟速度了解text-align match-parent声明 « 张鑫旭-鑫空间-鑫生活 光标的形状也能设置了,就是CSS caret-shape属性 « 张鑫旭-鑫空间-鑫生活 pretext与文字四面环绕效果的实现 « 张鑫旭-鑫空间-鑫生活 JSON.rawJSON方法的作用是什么? « 张鑫旭-鑫空间-鑫生活 如何使用CSS判断鼠标从哪个方向进入元素? « 张鑫旭-鑫空间-鑫生活 借助mediabunny纯JS实现视频水印、剪裁、合成等功能 « 张鑫旭-鑫空间-鑫生活 务必谨慎使用JS WeakRef弱引用 « 张鑫旭-鑫空间-鑫生活 CSS六边形头像的实现与蜂巢布局 « 张鑫旭-鑫空间-鑫生活 CSS corner-shape与背景底纹技术 « 张鑫旭-鑫空间-鑫生活 浅学WebTransport API:下一代Web双向通信技术 « 张鑫旭-鑫空间-鑫生活 HTML dialog元素新支持了closedBy属性 « 张鑫旭-鑫空间-鑫生活 HTML interestfor属性与悬停popover交互效果 « 张鑫旭-鑫空间-鑫生活 CSS3模拟window7炫酷界面效果展示 « 张鑫旭-鑫空间-鑫生活 图片旋转+剪裁js插件(兼容各浏览器) « 张鑫旭-鑫空间-鑫生活 纯js无图片无外链CSS图片幻灯片播放插件 « 张鑫旭-鑫空间-鑫生活 CSS border三角、圆角图形生成技术简介 « 张鑫旭-鑫空间-鑫生活 CSS “渐进增强”在web制作中常见应用举例 « 张鑫旭-鑫空间-鑫生活 让IE6/IE7/IE8浏览器支持CSS3属性 « 张鑫旭-鑫空间-鑫生活 jQuery – 高亮动态显示页面HTML代码插件 « 张鑫旭-鑫空间-鑫生活 翻译 – 逐渐消失的Flash网站 « 张鑫旭-鑫空间-鑫生活 CSS reset的重新审视 – 避免样式重置 « 张鑫旭-鑫空间-鑫生活 新浪微博插入话题后部分文字选中的js实现 « 张鑫旭-鑫空间-鑫生活 JavaScript实现http地址自动检测并添加URL链接 « 张鑫旭-鑫空间-鑫生活 CSS实现兼容性的渐变背景(gradient)效果 « 张鑫旭-鑫空间-鑫生活 CSS content内容生成技术以及应用 « 张鑫旭-鑫空间-鑫生活 CSS gradient渐变之webkit核心浏览器下的使用 « 张鑫旭-鑫空间-鑫生活 CSS渐变之CSS3 gradient在Firefox3.6下的使用 « 张鑫旭-鑫空间-鑫生活 区分IE8/IE7/IE6及其他浏览器-CSS “\9″hack « 张鑫旭-鑫空间-鑫生活 CSS实现跨浏览器兼容性的盒阴影效果 « 张鑫旭-鑫空间-鑫生活 CSS3&HTML5各浏览器支持情况一览表 « 张鑫旭-鑫空间-鑫生活
使用::part伪元素改变Shadow DOM的CSS样式 « 张鑫旭-鑫空间-...
张鑫旭,zhangxinxu · 2021-02-06 · via 张鑫旭-鑫空间-鑫生活

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=9789
本文欢迎分享与聚合,请勿全文转载,尊重版权,圈子就这么大,若急用可以联系授权或购买版权。

css part伪元素马儿开心跑占位图

一、历史-CSS变量穿越Shadow DOM

很早就开始关注如何让Shadow DOM外部的CSS代码改变Shadow DOM里面元素的样式。

一番探查下来,发现就CSS变量有穿透的作用。

举个例子,自定义了一个按钮,为<ui-button>元素:

<ui-button>按钮</ui-button>

为了还保持原本按钮无障碍访问特性,因此使用Shadow DOM插入了一个原生的<button>按钮,并配置默认的一些样式。相关JavaScript代码如下(假设<ui-button>元素对象是button):

var shadow = button.attachShadow({ mode: 'closed' });
// Shadow DOM中的样式和按钮 
shadow.innerHTML = `<style>
button {
    padding: 9px 1em;
    border: var(--ui-button-border, 1px solid #ccc);
    border-radius: var(--ui-button-radius, 4px);
    background-color: var(--ui-button-background, #fff);
    color:  var(--ui-button-color, #333);
}
</style>
<button>${button.textContent}</button>`;

此时的Shadow DOM结构如下图所示。

此时,通过在外部设置CSS变量就可以改变Shadow DOM内元素的样式,假设设置了如下HTML和CSS:

<ui-button type="primary">按钮</ui-button>
[type="primary"] {
    --ui-button-border: 1px solid transparent;
    --ui-button-background: deepskyblue;
    --ui-button-color: #fff;
}

则原始按钮和设置CSS自定义属性改变样式后的按钮对比效果如下所示。


因此,很长一段时间内,我都以为目前只有CSS变量可以穿透Shadow DOM改变里面的样式。

后来经同事提醒,浏览器已经支持了::part伪元素。

我一查看,果然,瞧着绿油油的一片,是不是有金山银山的感觉:

::part选择器兼容性

只要主流版本支持,就已经可以玩起来了。

//zxx: 如果你看到这段文字,说明你现在访问是体验糟糕的垃圾盗版网站,你可以访问原文获得很好的体验:https://www.zhangxinxu.com/wordpress/?p=9789(作者张鑫旭)

二、::part伪元素语法

CSS ::part这个选择器就是用来改变Shadow DOM元素样式的。

语法如下:

::part(xxxx)

xxxx是Shadow DOM元素的part属性值。

举个例子,例如上面CSS变量改变自定义元素样式的代码如果改用::part伪元素实现就可以这么处理:

class UiButton extends HTMLElement {
    constructor() {
        super();
    }
    connectedCallback () {
        let shadow = this.attachShadow({ mode: 'closed' });
        // Shadow DOM中的样式和按钮
        shadow.innerHTML = `<style>
            button {
                padding: 9px 1em;
                border: 1px solid #ccc;
                border-radius: 4px;
                background-color: #fff;
                color: #333;
            }
        </style>
        <button part="button">${this.textContent}</button>`;
    }
};
// 注册
customElements.define('ui-button', UiButton);

此时,重置按钮的样式就无需借助CSS变量穿透了,直接使用::part伪元素即可,示意如下:

<ui-button title="by zhangxinxu">按钮</ui-button>
<ui-button type="primary">按钮 - type="parimary"</ui-button>
[type="primary"]::part(button) {
    border-color: transparent;
    background-color: deepskyblue;
    color: #fff;
}

效果如下所示:

::part与按钮样式变化截图

眼见为实,您可以狠狠地点击这里:CSS ::part改变按钮Shadow DOM样式demo

//zxx: 如您发现文章盗版,欢迎反馈或向平台举报

三、深入<slot>与样式设置细节

使用Shadow DOM开发自定义元素组件的时候,常常会使用<slot>元素进行占位,此时,<slot>内部的元素样式是否可以使用::part伪元素设置呢?

我们直接看一个例子,此例子源自“HTMLUnknownElement与HTML5自定义元素”最后的<zxx-info>自定义元素。

是这样的,组件模板HTML如下:

<template id="tplZxxInfo">
    <style>
        :host { display: flow-root; }
        img { float: left; margin-right: 10px; }
        p { margin: .5em 0;}
    </style>
    <img part="img" loading="lazy" src="https://image.zhangxinxu.com/image/blog/zxx_240_0818.jpg">
    <slot name="description" part="description">这是显示描述信息</slot>
</template>

其中描述信息使用<slot>元素占位,大家可以理解为“替身使者”。

然后页面中的CSS和HTML是这样的:

/* 下面3段CSS语句哪个可以影响文字样式呢? */
zxx-info::part(description) {
    color: deepskyblue;
}
zxx-info::part(description) p {
    color: red;
}
zxx-info p {
    border-bottom: 1px dashed;
}
<zxx-info>
    <p slot="description">张鑫旭-鑫空间-鑫生活</p>
    <p slot="description">帅锅一枚</p>
    <p slot="description">文字颜色红色么?下划线有了么?</p>
</zxx-info>

其中,对于<p>元素,有4处CSS都尝试对其进行样式设置,分别是:

  1. Shadow DOM中的p { margin: .5em 0;}
  2. 外部CSS样式中的 zxx-info::part(description),也即是<slot>元素,说不定颜色可以继承下去。
  3. 外部CSS样式中的 zxx-info::part(description) p {}
  4. 外部CSS样式中的 zxx-info p {}

请问大家,上面4段CSS,哪些是可以让<zxx-info>中的文字发生样式变化的?

出人意料的结果

结果是第2行和第4行的选择器语句有效。

最终样式效果如下截图所示:

颜色深天蓝,有虚线下划线

文字是深天蓝色,说明zxx-info::part(description)可以影响里面文字,同时文字有下划虚线,说明zxx-info p选择器的匹配是有效的。

眼见为实,您可以狠狠地点击这里:CSS ::part与Shadow DOM slot样式demo

深究slot特性

我们来深入探究下。

此时,<zxx-info>自定义元素的完整DOM结构示意是这样的:

slot元素展开示意

可以看到,<slot>元素中有灰色的<p>元素(参见上图区域A),这些<p>元素大家可以理解为“替身使者”,“本体”<p>元素此时依然作为非Shadow DOM元素显示在在<zxx-info>元素中(参见上图区域B)。

无论是对“替身使者”还是“本体”<p>元素进行样式设置,都可以改变文字显示的颜色。

只是区域A中这些<p>元素有形无实(浏览器置灰了),无法通过zxx-info::part(description) p {}这个选择器进行匹配,因此,color:red设置红色是无效的。

虽然无法使用标签进行匹配,但是,却可以继承祖先元素,也就是可以继承<slot>元素的颜色、行高,字体等样式,因此,最终的文字颜色是可以受下面CSS影响的,最终表现为深天蓝色:

zxx-info::part(description) {
    color: deepskyblue;
}

至于zxx-info p{}有效,则是因为区域B中的 <p> 元素就是<zxx-info>元素的子元素。

四、无中生有学到的知识

学习CSS ::part伪元素,无意中让自己搞清楚了<slot>元素的样式渲染规则,真是额外的收获。

回头有机会可以把<slot>元素额外拎出来讲下。

一番体验下来,CSS ::part伪元素比预想的要好看,确实可以用起来了。

等以后IE浏览器拜拜了,Web将会是Web Components的舞台,届时,Shadow DOM相关知识估计会掀起一小波热度。

现在嘛,环境不允许,火不起来,都是小范围传播。

好,就说这么多。

祝大家春节快乐,记得分享哦~

本文为原创文章,欢迎分享,勿全文转载,如果实在喜欢,可收藏,永不过期,且会及时更新知识点及修正错误,阅读体验也更好。
本文地址:https://www.zhangxinxu.com/wordpress/?p=9789

(本篇完)