template component html css css3 dom web-component

html - component - Valores css de tamaño de fuente basados en la raíz de DOM Shadow



web components lifecycle (3)

Breve descripción del problema:

Estoy buscando una manera de establecer valores basados ​​en el tamaño de fuente (similar a establecer alguna propiedad en un valor em) en un elemento dentro de un dom de sombra relativo al host de sombra, independientemente del tamaño de fuente del elemento principal en el dom de sombra. Algo similar a cómo funcionan los valores rem, pero con la sombra como raíz en lugar de la raíz html.

El motivo de esto es poder escalar el contenido como un widget (que se inserta con la sombra) en un solo lugar. Si las propiedades que se basan en el tamaño de fuente se pueden escalar de esta manera, se puede escalar un widget completo en cada contexto sin tener que establecer muchos valores de css para que se ajuste a cada ubicación.

Descripción larga del problema:

Estoy buscando una manera de dimensionar el texto (tamaño de fuente) basado en un elemento dado en el DOM, para poder escalar diferentes partes del contenido dentro de ese elemento basado en este elemento de ajuste (bueno para los widgets y demás). Esto no es solo para el texto real, a menudo es bueno basar una gran cantidad de valores css en el tamaño de fuente, por lo que los elementos del diseño visual se escalan con el tamaño del texto (como el relleno, el radio del borde y las sombras). Si todo se basa en valores em, esto puede ser un poco desordenado. Si hay múltiples niveles de tamaño de fuente heredados dentro del elemento, y quiero ampliar el primer nivel sin cambiar el segundo, necesitaría ampliar el nivel del primer nivel en el dom, al mismo tiempo que reduzco cualquier elemento de segundo nivel. (que se calcula en función de ese primer nivel) para que el texto de los subelementos permanezca del mismo tamaño. Esto es menos que óptimo en muchos casos.

Una buena solución es basar las cosas en Root EM (rem), por lo que cambiar un nivel del dominio no afecta a los subelementos. Sin embargo, si quiero aumentar / reducir el tamaño de todo el texto dentro de estos elementos de ajuste (en un lugar) sin afectar a los otros elementos en la misma página, necesitaría aumentar / reducir los valores remotos de todos los tamaños de fuente para Elementos dentro de ese elemento de envoltura.

Recientemente comencé a buscar en componentes web con Shadow DOM y plantillas. En las etiquetas de plantilla, css está encapsulado, lo cual es genial porque el diseño de esa caja / widget / componente se puede diseñar por sí solo sin tener que pensar en el resto del diseño, los valores heredados no deseados y demás. Finalmente, una buena manera de hacer componentes independientes para construir una página web. Pero sería genial si pudiera establecer un tipo de fuente de tamaño de fuente para la plantilla en sí. Entonces, si configuro algún elemento dentro de la plantilla para que sea de tamaño fuente 2rem (o cualquier otra unidad similar), entonces el tamaño de fuente de ese elemento sería 2x el tamaño de fuente raíz de la plantilla, independientemente del tamaño de fuente en el host elemento donde se utiliza esa plantilla, e independientemente del tamaño de fuente de la raíz de la página (el elemento html).

Cuando probé con valores rem dentro de una plantilla, aún estaba basado en el tamaño de fuente de la raíz de la página (etiqueta html). También he probado los valores de vw, pero esto también se basa en toda la ventana gráfica, y no solo en el área encapsulada (la raíz sombreada).

He visto muchos artículos sobre Shadow DOM, pero no he podido encontrar ninguna solución a este problema. ¿Alguna sugerencia?

Qué pasa (ejemplos simplificados):

<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>

Lo que quiero:

<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>

Esto le daría un lugar (la parte: raíz del ejemplo anterior) para controlar todos los tamaños de fuente relativos dentro de ese componente, y esto puede combinarse con tamaños de fuente no relativos como px u otros valores css normales.


Después de revisar los documentos del Componente Web. Su ejemplo de lo que quiere hacer no se parece en nada a un componente web. Vea el siguiente ejemplo de componente web.

en el encabezado de tu documento tendrías

<link rel="import" href="web_component_name.html"></link>

en el cuerpo tendrías

<my-web-component>Bob</my-web-component>

su componente web tendría entonces su propio archivo.

<html> <template id="nameTagTemplate"> <style> .outer { border: 2px solid brown; border-radius: 1em; background: red; font-size: 20pt; width: 12em; height: 7em; text-align: center; } .boilerplate { color: white; font-family: sans-serif; padding: 0.5em; } .name { color: black; background: white; font-family: "Marker Felt", cursive; font-size: 45pt; padding-top: 0.2em; } </style> <div class="outer"> <div class="boilerplate"> Hi! My name is </div> <div class="name"> <content></content> </div> </div> </template> <script> var importDoc = document.currentScript.ownerDocument; var nameBadgePrototype = Object.create(HTMLElement.prototype); nameBadgePrototype.createdCallback = function() { var shadow = this.createShadowRoot(); var template = importDoc.querySelector(''#nameTagTemplate''); shadow.appendChild(template.content.cloneNode(true)); }; document.registerElement("my-web-component", { prototype: nameBadgePrototype }); </script> </html>

Su ejemplo de lo que intenta hacer y lo que realmente quiere no coincide. Después de algunas respuestas tuyas, veo que quieres hacer componentes web. Esto no es lo que mostraba en su ejemplo de lo que intenta hacer. Además, este código solo funciona si ha habilitado los indicadores correctos en su navegador web Chrome Canary. No funcionará de forma predeterminada y necesita que el usuario habilite la configuración beta correcta para que funcione. Incluso en una intranet no recomendaría el uso de componentes web, ya que todavía es muy beta y tendrá muchos problemas para mantener esto con muchos usuarios internos. Los usuarios encuentran formas de restablecer la configuración en el navegador todo el tiempo. Los usuarios rompen todo lo nuevo y brillante.


El problema es que está llamando a un objeto DOM una "raíz sombra", lo que tiene es otro elemento DOM que es una rama de la raíz. La plantilla de etiqueta no tiene un significado especial en HTML5. No hay tal cosa como una "raíz de sombra". Hay varias formas de inyectar un documento en otro documento. utilizando iframes, etiquetas de objeto, etiquetas de elementos. No recomiendo hacer ninguno de ellos ya que rompe la capacidad de que el documento se analice correctamente junto con una larga lista de otros problemas futuros que tendrá.

Su mejor opción es crear un elemento DOM en CSS que tenga los atributos básicos con los que desea comenzar y usar css para hacer que los sub elementos de ese elemento cambien según su css. Puede crear una plantilla de elemento DOM en css y darle un estilo base.

Archivo CSS

template{ font-size: 20px; }

archivo html

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

esto establecerá cualquier elemento DOM denominado plantilla al tamaño de fuente 20px y todos los elementos sub dom cambiarán según el elemento principal. Además, trate de no usar el estilo en línea en los elementos, los selectores de CSS pueden hacer mucho trabajo por usted.


El selector de :host diseña el elemento que hospeda la raíz de la sombra. Esto tiene el mismo efecto que diseñar el elemento host con el css / styles externo (por ejemplo, <div id="rootelm" style="font-size:20px"></div> para el ejemplo a continuación). Si usas :host lugar de tu falso :root selector de :root , debería funcionar como esperas. Aquí hay un ejemplo:

<!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>

plunker

EDIT: se actualizó el plunker con JS para hacer tamaños de fuente en relación con el elemento que aloja la raíz de la sombra. Script se reproduce a continuación.

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(); }