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值)组合.
选择器: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)
编辑:使用 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)