IE11: ¿existe un polyfill/script para las variables CSS?
polyfill js (4)
+1 para el enlace del fragmento de código-lápiz en la sección de comentarios de preguntas anterior de [I kode]. Sin embargo, una cosa que encontré es que el fragmento debe modificarse ligeramente para tener las declaraciones de funciones definidas en el formato JSON para que IE11 no se queje. A continuación se muestra la versión ligeramente modificada del fragmento de código de la pluma:
let cssVarPoly = {
init: function() {
// first lets see if the browser supports CSS variables
// No version of IE supports window.CSS.supports, so if that isn''t supported in the first place we know CSS variables is not supported
// Edge supports supports, so check for actual variable support
if (window.CSS && window.CSS.supports && window.CSS.supports(''(--foo: red)'')) {
// this browser does support variables, abort
console.log(''your browser supports CSS variables, aborting and letting the native support handle things.'');
return;
} else {
// edge barfs on console statements if the console is not open... lame!
console.log(''no support for you! polyfill all (some of) the things!!'');
document.querySelector(''body'').classList.add(''cssvars-polyfilled'');
}
cssVarPoly.ratifiedVars = {};
cssVarPoly.varsByBlock = {};
cssVarPoly.oldCSS = {};
// start things off
cssVarPoly.findCSS();
cssVarPoly.updateCSS();
},
// find all the css blocks, save off the content, and look for variables
findCSS: function() {
let styleBlocks = document.querySelectorAll(''style:not(.inserted),link[type="text/css"]'');
// we need to track the order of the style/link elements when we save off the CSS, set a counter
let counter = 1;
// loop through all CSS blocks looking for CSS variables being set
[].forEach.call(styleBlocks, function (block) {
// console.log(block.nodeName);
let theCSS;
if (block.nodeName === ''STYLE'') {
// console.log("style");
theCSS = block.innerHTML;
cssVarPoly.findSetters(theCSS, counter);
} else if (block.nodeName === ''LINK'') {
// console.log("link");
cssVarPoly.getLink(block.getAttribute(''href''), counter, function (counter, request) {
cssVarPoly.findSetters(request.responseText, counter);
cssVarPoly.oldCSS[counter] = request.responseText;
cssVarPoly.updateCSS();
});
theCSS = '''';
}
// save off the CSS to parse through again later. the value may be empty for links that are waiting for their ajax return, but this will maintain the order
cssVarPoly.oldCSS[counter] = theCSS;
counter++;
});
},
// find all the "--variable: value" matches in a provided block of CSS and add them to the master list
findSetters: function(theCSS, counter) {
// console.log(theCSS);
cssVarPoly.varsByBlock[counter] = theCSS.match(/(--.+:.+;)/g) || [];
},
// run through all the CSS blocks to update the variables and then inject on the page
updateCSS: function() {
// first lets loop through all the variables to make sure later vars trump earlier vars
cssVarPoly.ratifySetters(cssVarPoly.varsByBlock);
// loop through the css blocks (styles and links)
for (let curCSSID in cssVarPoly.oldCSS) {
// console.log("curCSS:",oldCSS[curCSSID]);
let newCSS = cssVarPoly.replaceGetters(cssVarPoly.oldCSS[curCSSID], cssVarPoly.ratifiedVars);
// put it back into the page
// first check to see if this block exists already
if (document.querySelector(''#inserted'' + curCSSID)) {
// console.log("updating")
document.querySelector(''#inserted'' + curCSSID).innerHTML = newCSS;
} else {
// console.log("adding");
var style = document.createElement(''style'');
style.type = ''text/css'';
style.innerHTML = newCSS;
style.classList.add(''inserted'');
style.id = ''inserted'' + curCSSID;
document.getElementsByTagName(''head'')[0].appendChild(style);
}
};
},
// parse a provided block of CSS looking for a provided list of variables and replace the --var-name with the correct value
replaceGetters: function(curCSS, varList) {
// console.log(varList);
for (let theVar in varList) {
// console.log(theVar);
// match the variable with the actual variable name
let getterRegex = new RegExp(''var//(//s*'' + theVar + ''//s*//)'', ''g'');
// console.log(getterRegex);
// console.log(curCSS);
curCSS = curCSS.replace(getterRegex, varList[theVar]);
// now check for any getters that are left that have fallbacks
let getterRegex2 = new RegExp(''var//(//s*.+//s*,//s*(.+)//)'', ''g'');
// console.log(getterRegex);
// console.log(curCSS);
let matches = curCSS.match(getterRegex2);
if (matches) {
// console.log("matches",matches);
matches.forEach(function (match) {
// console.log(match.match(/var/(.+,/s*(.+)/)/))
// find the fallback within the getter
curCSS = curCSS.replace(match, match.match(/var/(.+,/s*(.+)/)/)[1]);
});
}
// curCSS = curCSS.replace(getterRegex2,varList[theVar]);
};
// console.log(curCSS);
return curCSS;
},
// determine the css variable name value pair and track the latest
ratifySetters: function(varList) {
// console.log("varList:",varList);
// loop through each block in order, to maintain order specificity
for (let curBlock in varList) {
let curVars = varList[curBlock];
// console.log("curVars:",curVars);
// loop through each var in the block
curVars.forEach(function (theVar) {
// console.log(theVar);
// split on the name value pair separator
let matches = theVar.split(/:/s*/);
// console.log(matches);
// put it in an object based on the varName. Each time we do this it will override a previous use and so will always have the last set be the winner
// 0 = the name, 1 = the value, strip off the ; if it is there
cssVarPoly.ratifiedVars[matches[0]] = matches[1].replace(/;/, '''');
});
};
// console.log(ratifiedVars);
},
// get the CSS file (same domain for now)
getLink: function(url, counter, success) {
var request = new XMLHttpRequest();
request.open(''GET'', url, true);
request.overrideMimeType(''text/css;'');
request.onload = function () {
if (request.status >= 200 && request.status < 400) {
// Success!
// console.log(request.responseText);
if (typeof success === ''function'') {
success(counter, request);
}
} else {
// We reached our target server, but it returned an error
console.warn(''an error was returned from:'', url);
}
};
request.onerror = function () {
// There was a connection error of some sort
console.warn(''we could not get anything from:'', url);
};
request.send();
}
};
cssVarPoly.init();
Estoy desarrollando una página web en un entorno de navegador web mixto (Chrome / IE11). IE11 no admite variables CSS, ¿existe un polyfill o script que me permita usar variables CSS en IE11?
Este polyfill permite un soporte casi completo para las propiedades personalizadas en IE11:
github.com/nuxodin/ie11CustomProperties
Cómo funciona
El script hace uso del hecho de que IE tiene un soporte mínimo de propiedades personalizadas donde las propiedades se pueden definir y leer teniendo en cuenta la cascada.
.myEl {-ie-test:''aaa''} // only one dash allowed! "-"
luego léelo en javascript:
getComputedStyle( querySelector(''.myEl'') )[''-ie-test'']
Características del archivo README:
- maneja contenido html agregado dinámico
- maneja dinámico agregado, -elementos
- encadenamiento
--bar:var(--foo)
- Fallback
var(--color, blue)
- : focus,: target,: hover
- integración js:
style.setProperty(''--x'',''y'')
style.getPropertyValue(''--x'')
getComputedStyle(el).getPropertyValue(''--inherited'')
- Estilos en línea:
<div ie-style="--color:blue"...
- trabajos en cascada
- herencia obras
- bajo 3k (min + gzip) y sin dependencia
Manifestación:
Probé esta versión de Polyfill pero terminé con errores cuando una línea en CSS tenía múltiples variables (fuente FI y color). Un colega mío me ayudó. Ver línea 94.
let cssVarPoly = {
init: function() {
// first lets see if the browser supports CSS variables
// No version of IE supports window.CSS.supports, so if that isn''t supported in the first place we know CSS variables is not supported
// Edge supports supports, so check for actual variable support
if (window.CSS && window.CSS.supports && window.CSS.supports(''(--foo: red)'')) {
// this browser does support variables, abort
// console.log(''your browser supports CSS variables, aborting and letting the native support handle things.'');
return;
} else {
// edge barfs on console statements if the console is not open... lame!
// console.log(''no support for you! polyfill all (some of) the things!!'');
document.querySelector(''body'').classList.add(''cssvars-polyfilled'');
}
cssVarPoly.ratifiedVars = {};
cssVarPoly.varsByBlock = {};
cssVarPoly.oldCSS = {};
// start things off
cssVarPoly.findCSS();
cssVarPoly.updateCSS();
},
// find all the css blocks, save off the content, and look for variables
findCSS: function() {
let styleBlocks = document.querySelectorAll(''style:not(.inserted),link[type="text/css"]'');
// we need to track the order of the style/link elements when we save off the CSS, set a counter
let counter = 1;
// loop through all CSS blocks looking for CSS variables being set
[].forEach.call(styleBlocks, function (block) {
// console.log(block.nodeName);
let theCSS;
if (block.nodeName === ''STYLE'') {
// console.log("style");
theCSS = block.innerHTML;
cssVarPoly.findSetters(theCSS, counter);
} else if (block.nodeName === ''LINK'') {
// console.log("link");
cssVarPoly.getLink(block.getAttribute(''href''), counter, function (counter, request) {
cssVarPoly.findSetters(request.responseText, counter);
cssVarPoly.oldCSS[counter] = request.responseText;
cssVarPoly.updateCSS();
});
theCSS = '''';
}
// save off the CSS to parse through again later. the value may be empty for links that are waiting for their ajax return, but this will maintain the order
cssVarPoly.oldCSS[counter] = theCSS;
counter++;
});
},
// find all the "--variable: value" matches in a provided block of CSS and add them to the master list
findSetters: function(theCSS, counter) {
// console.log(theCSS);
cssVarPoly.varsByBlock[counter] = theCSS.match(/(--.+:.+;)/g) || [];
},
// run through all the CSS blocks to update the variables and then inject on the page
updateCSS: function() {
// first lets loop through all the variables to make sure later vars trump earlier vars
cssVarPoly.ratifySetters(cssVarPoly.varsByBlock);
// loop through the css blocks (styles and links)
for (let curCSSID in cssVarPoly.oldCSS) {
// console.log("curCSS:",oldCSS[curCSSID]);
let newCSS = cssVarPoly.replaceGetters(cssVarPoly.oldCSS[curCSSID], cssVarPoly.ratifiedVars);
// put it back into the page
// first check to see if this block exists already
if (document.querySelector(''#inserted'' + curCSSID)) {
// console.log("updating")
document.querySelector(''#inserted'' + curCSSID).innerHTML = newCSS;
} else {
// console.log("adding");
var style = document.createElement(''style'');
style.type = ''text/css'';
style.innerHTML = newCSS;
style.classList.add(''inserted'');
style.id = ''inserted'' + curCSSID;
document.getElementsByTagName(''head'')[0].appendChild(style);
}
};
},
// parse a provided block of CSS looking for a provided list of variables and replace the --var-name with the correct value
replaceGetters: function(curCSS, varList) {
// console.log(varList);
for (let theVar in varList) {
// console.log(theVar);
// match the variable with the actual variable name
// console.log (theVar);
var res = theVar.match(/--[a-zA-Z0-9-]+/g);
// console.log (res[0]);
theVar = res[0];
let getterRegex = new RegExp(''var//(//s*'' + theVar + ''//s*//)'', ''g'');
// console.log(getterRegex);
// console.log(curCSS);
curCSS = curCSS.replace(getterRegex, varList[theVar]);
// now check for any getters that are left that have fallbacks
let getterRegex2 = new RegExp(''var//(//s*.+//s*,//s*(.+)//)'', ''g'');
// console.log(getterRegex);
// console.log(curCSS);
let matches = curCSS.match(getterRegex2);
if (matches) {
// console.log("matches",matches);
matches.forEach(function (match) {
// console.log(match.match(/var/(.+,/s*(.+)/)/))
// find the fallback within the getter
curCSS = curCSS.replace(match, match.match(/var/(.+,/s*(.+)/)/)[1]);
});
}
// curCSS = curCSS.replace(getterRegex2,varList[theVar]);
};
// console.log(curCSS);
return curCSS;
},
// determine the css variable name value pair and track the latest
ratifySetters: function(varList) {
// console.log("varList:",varList);
// loop through each block in order, to maintain order specificity
for (let curBlock in varList) {
let curVars = varList[curBlock];
// console.log("curVars:",curVars);
// loop through each var in the block
curVars.forEach(function (theVar) {
// console.log(theVar);
// split on the name value pair separator
let matches = theVar.split(/:/s*/);
// console.log(matches);
// put it in an object based on the varName. Each time we do this it will override a previous use and so will always have the last set be the winner
// 0 = the name, 1 = the value, strip off the ; if it is there
cssVarPoly.ratifiedVars[matches[0]] = matches[1].replace(/;/, '''');
});
};
// console.log(ratifiedVars);
},
// get the CSS file (same domain for now)
getLink: function(url, counter, success) {
var request = new XMLHttpRequest();
request.open(''GET'', url, true);
request.overrideMimeType(''text/css;'');
request.onload = function () {
if (request.status >= 200 && request.status < 400) {
// Success!
// console.log(request.responseText);
if (typeof success === ''function'') {
success(counter, request);
}
} else {
// We reached our target server, but it returned an error
console.warn(''an error was returned from:'', url);
}
};
request.onerror = function () {
// There was a connection error of some sort
console.warn(''we could not get anything from:'', url);
};
request.send();
}
};
cssVarPoly.init();
Sí, siempre que esté procesando propiedades personalizadas de nivel raíz (IE9 +).
- GitHub : https://github.com/jhildenbiddle/css-vars-ponyfill
- NPM : https://www.npmjs.com/package/css-vars-ponyfill
- Demostración : https://codepen.io/jhildenbiddle/pen/ZxYJrR
Desde el archivo Léame:
Caracteristicas
- Transformación del lado del cliente de propiedades personalizadas CSS a valores estáticos
- Actualizaciones en vivo de valores de tiempo de ejecución en navegadores modernos y antiguos
- Transforma
<link>
,<style>
y@import
CSS- Transforma las rutas relativas
url()
a URL absolutas- Admite funciones
var()
encadenadas y anidadas- Admite valores de recuperación de la función
var()
- Admite componentes web / shadow DOM CSS
- Ver actualizaciones automáticas del modo en los cambios
<link>
y<style>
- Módulo UMD y ES6 disponible
- Definiciones de TypeScript incluidas
- Ligero (6k min + gzip) y sin dependencia
Limitaciones
- El soporte de propiedad personalizada se limita a: declaraciones raíz
- El uso de var () está limitado a valores de propiedad (según la https://github.com/jhildenbiddle/css-vars-ponyfill )
Aquí hay algunos ejemplos de lo que la biblioteca puede manejar:
Propiedades personalizadas de nivel raíz
:root {
--a: red;
}
p {
color: var(--a);
}
Propiedades personalizadas encadenadas
:root {
--a: var(--b);
--b: var(--c);
--c: red;
}
p {
color: var(--a);
}
Propiedades personalizadas anidadas
:root {
--a: 1em;
--b: 2;
}
p {
font-size: calc(var(--a) * var(--b));
}
Valores de reserva
p {
font-size: var(--a, 1rem);
color: var(--b, var(--c, var(--d, red)));
}
Transforma
<link>
,
<style>
y
@import
CSS
<link rel="stylesheet" href="/absolute/path/to/style.css">
<link rel="stylesheet" href="../relative/path/to/style.css">
<style>
@import "/absolute/path/to/style.css";
@import "../relative/path/to/style.css";
</style>
Transforma componentes web / DOM sombra
<custom-element>
#shadow-root
<style>
.my-custom-element {
color: var(--test-color);
}
</style>
<div class="my-custom-element">Hello.</div>
</custom-element>
En aras de la integridad: especificaciones w3c
Espero que esto ayude.
(Auto-promoción descarada: Cheque)