基于Shadow DOM root的字体大小css值

hen*_*nit 20 html css dom css3 web-component

问题简述:

我正在寻找一种方法来设置基于字体大小的值(类似于将一些属性设置为em值)在阴影dom内相对于阴影主机的元素内,而不管阴影dom中父元素的字体大小.类似于rem-values的工作原理,但是阴影是root而不是html root.

这样做的原因是能够在一个地方缩放像小部件(插入阴影dom)的内容.如果可以通过这种方式缩放基于字体大小的属性,则可以在每个上下文中缩放整个窗口小部件,而无需设置大量css值以使其适合每个位置.

问题的详细描述:

我正在寻找一种基于DOM中的给定元素来调整文本大小(font-size)的方法,以便能够基于此包装元素缩放该元素内的不同内容部分(适用于小部件等).这不仅仅适用于实际文本,通常很好地基于font-size来设置很多css值,因此元素的可视化布局与文本的大小(如填充,边框半径和阴影)一致.如果一切都基于em值,这可能会有点混乱.如果元素中有多个级别的字体大小继承,并且我想在不改变第二级的情况下放大第一级,我需要放大dom中第一级的em,同时减少任何二级元素(基于第一级计算)使子元素的文本保持相同的大小.在许多情况下,这不是最佳的.

一个很好的解决方案是基于Root EM(rem),因此更改dom的一个级别不会影响子元素.但是,如果我想放大/缩小这个包装元素内的所有文本的大小(在一个地方)而不影响同一页面上的其他元素,我需要放大/缩小所有字体大小的rem值.包装元素内的元素.

我最近开始研究使用Shadow DOM和模板的Web组件.在模板标签中,css是封装的,因为该框/小部件/组件的设计可以独立设计,而不必考虑设计的其余部分,不需要的继承值等.最后是制作独立组件以构建网页的好方法.但是,如果我可以为模板本身设置一种模板根字体大小,那就太好了.因此,如果我将模板中的某些元素设置为font-size 2rem(或任何其他类似单位),那么该元素的字体大小将是模板的根字体大小的2倍,而不管主机中的字体大小如何使用该模板的元素,无论页面根目录的字体大小(html元素)如何.

当我在模板中使用rem-values进行测试时,它仍然基于页面根(html标签)font-size.我也测试了vw值,但这也是基于整个视口,而不仅仅是封装区域(阴影根).

我看过很多关于Shadow DOM的文章,但我还没有找到任何关于这个问题的解决方案.有什么建议?

会发生什么(简化示例):

<html style="font-size: 16px">
    <body style="font-size: 12px">
        I am 12px large

        <!-- em, based on the body in this case -->
        <div style="font-size: 1.5em">
            I am 18px large

            <div style="font-size: 1.5em">
                I am 27px large
            </div>
        </div>

        <!-- rem, based on the styles of the html element -->
        <div style="font-size: 1.5rem">
            I am 24px large

            <div style="font-size: 1.5rem">
                I am 24px large
            </div>
        </div>
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)

我想要的是:

<html style="font-size: 16px">
    <body style="font-size: 12px">
        I am 12px large

        <div style="font-size: 1.5em">
            I am 18px large
        </div>
        <div style="font-size: 1.5rem">
            I am 24px large
        </div>

        <template> <!-- Simulates that it is inserted into the DOM by using shadow elements -->
            <style>
                :root{ /* Or something like that */
                    font-size: 20px; /* This is the simulated "template root fontsize" */
                }
            </style>

            <div style="font-size: 1.5trem"> <!-- Based on the template root fontsize -->
                I am 30px large

                <div style="font-size: 2trem">
                    I am 40px large
                </div>
            </div>

        </template>
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)

这将给出一个位置(上面示例的:根部分)来控制该组件内的所有相对字体大小,然后可以将其与非相对字体大小(如px或其他普通css值)组合.

quw*_*quw 0

选择器:host对承载影子根的元素进行样式设置。这与使用外部 css/样式设置宿主元素的样式具有相同的效果(例如<div id="rootelm" style="font-size:20px"></div>下面的示例)。如果您使用:host而不是假:root选择器,它应该按您的预期工作。这是一个例子:

<!DOCTYPE HTML>
<html style="font-size: 16px">
    <body style="font-size: 12px">
        I am 12px large

        <div style="font-size: 1.5em">
            I am 18px large
        </div>
        <div style="font-size: 1.5rem">
            I am 24px large
        </div>

        <div id="rootelm"></div>

        <template id="testtemplate">
            <style>
                :host{ /* Our new selector */
                    font-size: 20px; /* This is the "template root fontsize" */
                }
            </style>
            <div style="font-size: 1em">
                I am 20px large
                <!-- Absolute size for comparison -->
                <div style="font-size: 20px">I am 20px large as well</div>
                <div style="font-size: 2em">
                    I am 40px large
                    <!-- Absolute size for comparison -->
                    <div style="font-size: 40px">I am 40px large as well</div>
                </div>
            </div>
        </template>

        <script>
            var shadow = document.querySelector('#rootelm').createShadowRoot();
            var template = document.querySelector('#testtemplate');
            shadow.innerHTML = template.innerHTML;
        </script>
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)

plunker

编辑:使用 JS 更新了 plunker,以使字体大小相对于承载影子根的元素。脚本复制如下。

    function updateFontSizes() {
        //Get root element. If you had more than one, you could use querySelectorAll(), and loop over the resulting array
        var rootElm = document.querySelector("#rootelm");
        /*Get styled elements. If you were using external styles instead of inline,
          you'd have to use getComputedStyle or another method of getting CSS */
        var styledElms = rootElm.shadowRoot.querySelectorAll('[style]');
        //Get the root font size (the font size applied to the element containing the template)
        var rootFontSize = window.getComputedStyle(rootElm, null).getPropertyValue("font-size");
        //Format root fontsize. If you are using different units, change the string in IndexOF
        rootFontSize = parseFloat(rootFontSize.substring(0, rootFontSize.indexOf('px')).trim());
        for (var i = 0; i < styledElms.length; i++) {
            //Get relative font size index of units
            var unitIndex = styledElms[i].style.fontSize.indexOf('rem');
            //Get custom attribute that we will fill later
            var oldFS = styledElms[i].getAttribute("oldfs");
            //if font-size contains the relative units
            if (unitIndex > -1) {
                //Store relative font size in custom attribute
                styledElms[i].setAttribute("oldfs",styledElms[i].style.fontSize);
                //Set fontsize to relative font size * computed root font size
                styledElms[i].style.fontSize = parseFloat(styledElms[i].style.fontSize.substring(0, unitIndex).trim()) * rootFontSize + "px";
            }
            //If font size doesn't contain the relative units, and we stored the old relative font size
            else if (oldFS !== null) {
                //Set the fontsize to old relative font size * computed root font size
                styledElms[i].style.fontSize = parseFloat(oldFS.substring(0, oldFS.indexOf('rem')).trim()) * rootFontSize + "px"
            }
        }
    }

    //Media query listeners
    //See https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Testing_media_queries for more info
    var mql = window.matchMedia("(max-width: 500px)");
    mql.addListener(handleMediaQuery);
    handleMediaQuery(mql);

    function handleMediaQuery(mql) {
        updateFontSizes();
    }
Run Code Online (Sandbox Code Playgroud)