javascript - elementos - css after before ejemplos
Selección y manipulación de pseudo-elementos CSS, como:: before y:: after using jQuery (20)
¿Hay alguna forma de seleccionar / manipular pseudo-elementos CSS como ::before
y ::after
(y la versión anterior con un punto y coma) usando jQuery?
Por ejemplo, mi hoja de estilo tiene la siguiente regla:
.span::after{ content:''foo'' }
¿Cómo puedo cambiar ''foo'' a ''bar'' usando jQuery?
¡Gracias a todos! Logré hacer lo que quería: D http://jsfiddle.net/Tfc9j/42/ aquí eche un vistazo
Quería tener la opacidad de un div exterior para ser diferente de la opacidad del div interno y eso cambia con un clic en algún lugar;) ¡Gracias!
$(''#ena'').on(''click'', function () {
$(''head'').append("<style>#ena:before { opacity:0.3; }</style>");
});
$(''#duop'').on(''click'', function (e) {
$(''head'').append("<style>#ena:before { opacity:0.8; }</style>");
e.stopPropagation();
});
#ena{
width:300px;
height:300px;
border:1px black solid;
position:relative;
}
#duo{
opacity:1;
position:absolute;
top:50px;
width:300px;
height:100px;
background-color:white;
}
#ena:before {
content: attr(data-before);
color: white;
cursor: pointer;
position: absolute;
background-color:red;
opacity:0.9;
width:100%;
height:100%;
}
<div id="ena">
<div id="duo">
<p>ena p</p>
<p id="duop">duoyyyyyyyyyyyyyy p</p>
</div>
</div>
¿Por qué agregar clases o atributos cuando solo puede agregar un style
a la cabeza?
$(''head'').append(''<style>.span:after{ content:''changed content'' }</style>'')
Aquí está el HTML:
<div class="icon">
<span class="play">
::before
</span>
</div>
El estilo computado en "antes" era content: "VERIFY TO WATCH";
Aquí están mis dos líneas de jQuery, que usan la idea de agregar una clase adicional para hacer referencia específicamente a este elemento y luego agregar una etiqueta de estilo (con una etiqueta! Important) para cambiar el CSS del valor de contenido del elemento sudo:
$("span.play:eq(0)").addClass(''G'');
$(''body'').append("<style>.G:before{content:''NewText'' !important}</style>");
Aunque los navegadores los procesan a través de CSS como si fueran como otros elementos DOM reales, los pseudo-elementos en sí mismos no forman parte del DOM, porque los pseudo-elementos, como su nombre lo indica, no son elementos reales, y por lo tanto no se puede selecciónelos y manipúlelos directamente con jQuery (o cualquier API de JavaScript, ni siquiera la API de selectores ). Esto se aplica a cualquier pseudo-elementos cuyos estilos intenta modificar con un script, y no solo ::before
y ::after
.
Solo puede acceder a los estilos de pseudo-elementos directamente en el tiempo de ejecución a través de CSSOM (think window.getComputedStyle()
), que jQuery no expone más allá de .css()
, un método que tampoco admite pseudo-elementos.
Sin embargo, siempre puedes encontrar otras formas de evitarlo, por ejemplo:
Aplicar los estilos a los pseudo-elementos de una o más clases arbitrarias, luego alternar entre clases (ver la respuesta de seucolega para un ejemplo rápido) - esta es la forma idiomática ya que utiliza selectores simples (que no son pseudo-elementos) para Distinguir entre elementos y estados de elementos, la forma en que están destinados a ser utilizados
Manipular los estilos que se aplican a dichos pseudo-elementos, modificando la hoja de estilo del documento, que es mucho más que un hack
En la línea de lo que Christian sugiere, también podrías hacer:
$(''head'').append("<style>.span::after{ content:''bar'' }</style>");
Esta es la forma de acceder: después y: antes de las propiedades de estilo, definidas en css:
// Get the color value of .element:before
var color = window.getComputedStyle(
document.querySelector(''.element''), '':before''
).getPropertyValue(''color'');
// Get the content value of .element:before
var content = window.getComputedStyle(
document.querySelector(''.element''), '':before''
).getPropertyValue(''content'');
Esto no es práctico ya que no lo escribí para usos del mundo real, solo para darte un ejemplo de lo que se puede lograr.
css = {
before: function(elem,attr){
if($("#cust_style") !== undefined){
$("body").append("<style> " + elem + ":before {" + attr + "} </style>");
} else {
$("#cust_style").remove();
$("body").append("<style> " + elem + ":before {" + attr + "} </style>");
}
}, after: function(elem,attr){
if($("#cust_style") !== undefined){
$("body").append("<style> " + elem + ":after {" + attr + "} </style>");
} else { $("#cust_style").remove();
$("body").append("<style> " + elem + ":after {" + attr + "} </style>");
}
}
}
este actualmente agrega un / o agrega un elemento de estilo que contiene los atributos necesarios que tendrán efecto en el elemento de destino después del pseudo-elemento.
esto puede ser usado como
css.after("someElement"," content: ''Test''; position: ''absolute''; ") // editing / adding styles to :after
y
css.before( ... ); // to affect the before pseudo element.
como después: y antes: los pseudo elementos no son accesibles directamente a través de DOM, actualmente no es posible editar los valores específicos de css libremente.
Mi camino fue solo un ejemplo y no es bueno para la práctica. Puedes modificarlo, probar algunos de tus propios trucos y corregirlo para el uso en el mundo real.
Así que haz tu propia experimentación con esto y con otros!
Saludos - Adarsh Hegde.
Hay muchas respuestas aquí, pero ninguna respuesta ayuda a manipular el css de :before
o :after
, ni siquiera el aceptado.
Así es como me propongo hacerlo. Supongamos que su HTML es así:
<div id="something">Test</div>
Y luego está configurando su: antes en CSS y diseñándolo como:
#something:before{
content:"1st";
font-size:20px;
color:red;
}
#something{
content:''1st'';
}
Tenga en cuenta que también configuro el atributo de content
en el propio elemento para que pueda eliminarlo fácilmente más tarde. Ahora hay un button
clic en el que desea cambiar el color de: antes a verde y su tamaño de fuente a 30 px. Puedes lograrlo de la siguiente manera:
Defina un css con su estilo requerido en alguna clase .activeS
:
.activeS:before{
color:green !important;
font-size:30px !important;
}
Ahora puede cambiar: antes del estilo agregando la clase a su elemento: before de la siguiente manera:
<button id="changeBefore">Change</button>
<script>
$(''#changeBefore'').click(function(){
$(''#something'').addClass(''activeS'');
});
</script>
Si solo quieres obtener contenido de :before
, se puede hacer como:
<button id="getContent">Get Content</button>
<script>
$(''#getContent'').click(function(){
console.log($(''#something'').css(''content''));//will print ''1st''
});
</script>
En última instancia, si desea cambiar dinámicamente :before
contenido de jQuery, puede lograrlo de la siguiente manera:
<button id="changeBefore">Change</button>
<script>
var newValue = ''22'';//coming from somewhere
var add = ''<style>#something:before{content:"''+newValue+''"!important;}</style>'';
$(''#changeBefore'').click(function(){
$(''body'').append(add);
});
</script>
Al hacer clic en el botón "cambiar :before
", se cambiará :before
contenido de #something
en ''22'', que es un valor dinámico.
Espero que ayude
No puede seleccionar pseudo elementos en jQuery porque no son parte de DOM. Pero puede agregar una clase específica al elemento padre y controlar sus pseudo elementos en CSS.
En jQuery:
<script type="text/javascript">
$(''span'').addClass(''change'');
</script>
En CSS:
span.change:after { content: ''bar'' }
Puede crear una propiedad falsa o usar una existente y heredarla en la hoja de estilo del pseudo-elemento.
var switched = false;
// Enable color switching
setInterval(function () {
var color = switched ? ''red'' : ''darkred'';
var element = document.getElementById(''arrow'');
element.style.backgroundColor = color;
// Managing pseudo-element''s css
// using inheritance.
element.style.borderLeftColor = color;
switched = !switched;
}, 1000);
.arrow {
/* SET FICTIONAL PROPERTY */
border-left-color:red;
background-color:red;
width:1em;
height:1em;
display:inline-block;
position:relative;
}
.arrow:after {
border-top:1em solid transparent;
border-right:1em solid transparent;
border-bottom:1em solid transparent;
border-left:1em solid transparent;
/* INHERIT PROPERTY */
border-left-color:inherit;
content:"";
width:0;
height:0;
position:absolute;
left:100%;
top:-50%;
}
<span id="arrow" class="arrow"></span>
Parece que no funciona para la propiedad "content" :(
Puedes usar mi plugin para este propósito.
JQuery:
(function() {
$.pseudoElements = {
length: 0
};
var setPseudoElement = function(parameters) {
if (typeof parameters.argument === ''object'' || (parameters.argument !== undefined && parameters.property !== undefined)) {
for (var element of parameters.elements.get()) {
if (!element.pseudoElements) element.pseudoElements = {
styleSheet: null,
before: {
index: null,
properties: null
},
after: {
index: null,
properties: null
},
id: null
};
var selector = (function() {
if (element.pseudoElements.id !== null) {
if (Number(element.getAttribute(''data-pe--id'')) !== element.pseudoElements.id) element.setAttribute(''data-pe--id'', element.pseudoElements.id);
return ''[data-pe--id="'' + element.pseudoElements.id + ''"]::'' + parameters.pseudoElement;
} else {
var id = $.pseudoElements.length;
$.pseudoElements.length++
element.pseudoElements.id = id;
element.setAttribute(''data-pe--id'', id);
return ''[data-pe--id="'' + id + ''"]::'' + parameters.pseudoElement;
};
})();
if (!element.pseudoElements.styleSheet) {
if (document.styleSheets[0]) {
element.pseudoElements.styleSheet = document.styleSheets[0];
} else {
var styleSheet = document.createElement(''style'');
document.head.appendChild(styleSheet);
element.pseudoElements.styleSheet = styleSheet.sheet;
};
};
if (element.pseudoElements[parameters.pseudoElement].properties && element.pseudoElements[parameters.pseudoElement].index) {
element.pseudoElements.styleSheet.deleteRule(element.pseudoElements[parameters.pseudoElement].index);
};
if (typeof parameters.argument === ''object'') {
parameters.argument = $.extend({}, parameters.argument);
if (!element.pseudoElements[parameters.pseudoElement].properties && !element.pseudoElements[parameters.pseudoElement].index) {
var newIndex = element.pseudoElements.styleSheet.rules.length || element.pseudoElements.styleSheet.cssRules.length || element.pseudoElements.styleSheet.length;
element.pseudoElements[parameters.pseudoElement].index = newIndex;
element.pseudoElements[parameters.pseudoElement].properties = parameters.argument;
};
var properties = '''';
for (var property in parameters.argument) {
if (typeof parameters.argument[property] === ''function'')
element.pseudoElements[parameters.pseudoElement].properties[property] = parameters.argument[property]();
else
element.pseudoElements[parameters.pseudoElement].properties[property] = parameters.argument[property];
};
for (var property in element.pseudoElements[parameters.pseudoElement].properties) {
properties += property + '': '' + element.pseudoElements[parameters.pseudoElement].properties[property] + '' !important; '';
};
element.pseudoElements.styleSheet.addRule(selector, properties, element.pseudoElements[parameters.pseudoElement].index);
} else if (parameters.argument !== undefined && parameters.property !== undefined) {
if (!element.pseudoElements[parameters.pseudoElement].properties && !element.pseudoElements[parameters.pseudoElement].index) {
var newIndex = element.pseudoElements.styleSheet.rules.length || element.pseudoElements.styleSheet.cssRules.length || element.pseudoElements.styleSheet.length;
element.pseudoElements[parameters.pseudoElement].index = newIndex;
element.pseudoElements[parameters.pseudoElement].properties = {};
};
if (typeof parameters.property === ''function'')
element.pseudoElements[parameters.pseudoElement].properties[parameters.argument] = parameters.property();
else
element.pseudoElements[parameters.pseudoElement].properties[parameters.argument] = parameters.property;
var properties = '''';
for (var property in element.pseudoElements[parameters.pseudoElement].properties) {
properties += property + '': '' + element.pseudoElements[parameters.pseudoElement].properties[property] + '' !important; '';
};
element.pseudoElements.styleSheet.addRule(selector, properties, element.pseudoElements[parameters.pseudoElement].index);
};
};
return $(parameters.elements);
} else if (parameters.argument !== undefined && parameters.property === undefined) {
var element = $(parameters.elements).get(0);
var windowStyle = window.getComputedStyle(
element, ''::'' + parameters.pseudoElement
).getPropertyValue(parameters.argument);
if (element.pseudoElements) {
return $(parameters.elements).get(0).pseudoElements[parameters.pseudoElement].properties[parameters.argument] || windowStyle;
} else {
return windowStyle || null;
};
} else {
console.error(''Invalid values!'');
return false;
};
};
$.fn.cssBefore = function(argument, property) {
return setPseudoElement({
elements: this,
pseudoElement: ''before'',
argument: argument,
property: property
});
};
$.fn.cssAfter = function(argument, property) {
return setPseudoElement({
elements: this,
pseudoElement: ''after'',
argument: argument,
property: property
});
};
})();
$(function() {
$(''.element'').cssBefore(''content'', ''"New before!"'');
});
.element {
width: 480px;
margin: 0 auto;
border: 2px solid red;
}
.element::before {
content: ''Old before!'';
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div class="element"></div>
Los valores deben especificarse, como en la función normal de jQuery.css
Además, también puede obtener el valor del parámetro pseudo-elemento, como en la función normal de jQuery.css:
console.log( $(element).cssBefore(parameter) );
JS:
(function() {
document.pseudoElements = {
length: 0
};
var setPseudoElement = function(parameters) {
if (typeof parameters.argument === ''object'' || (parameters.argument !== undefined && parameters.property !== undefined)) {
if (!parameters.element.pseudoElements) parameters.element.pseudoElements = {
styleSheet: null,
before: {
index: null,
properties: null
},
after: {
index: null,
properties: null
},
id: null
};
var selector = (function() {
if (parameters.element.pseudoElements.id !== null) {
if (Number(parameters.element.getAttribute(''data-pe--id'')) !== parameters.element.pseudoElements.id) parameters.element.setAttribute(''data-pe--id'', parameters.element.pseudoElements.id);
return ''[data-pe--id="'' + parameters.element.pseudoElements.id + ''"]::'' + parameters.pseudoElement;
} else {
var id = document.pseudoElements.length;
document.pseudoElements.length++
parameters.element.pseudoElements.id = id;
parameters.element.setAttribute(''data-pe--id'', id);
return ''[data-pe--id="'' + id + ''"]::'' + parameters.pseudoElement;
};
})();
if (!parameters.element.pseudoElements.styleSheet) {
if (document.styleSheets[0]) {
parameters.element.pseudoElements.styleSheet = document.styleSheets[0];
} else {
var styleSheet = document.createElement(''style'');
document.head.appendChild(styleSheet);
parameters.element.pseudoElements.styleSheet = styleSheet.sheet;
};
};
if (parameters.element.pseudoElements[parameters.pseudoElement].properties && parameters.element.pseudoElements[parameters.pseudoElement].index) {
parameters.element.pseudoElements.styleSheet.deleteRule(parameters.element.pseudoElements[parameters.pseudoElement].index);
};
if (typeof parameters.argument === ''object'') {
parameters.argument = (function() {
var cloneObject = typeof parameters.argument.pop === ''function'' ? [] : {};
for (var property in parameters.argument) {
cloneObject[property] = parameters.argument[property];
};
return cloneObject;
})();
if (!parameters.element.pseudoElements[parameters.pseudoElement].properties && !parameters.element.pseudoElements[parameters.pseudoElement].index) {
var newIndex = parameters.element.pseudoElements.styleSheet.rules.length || parameters.element.pseudoElements.styleSheet.cssRules.length || parameters.element.pseudoElements.styleSheet.length;
parameters.element.pseudoElements[parameters.pseudoElement].index = newIndex;
parameters.element.pseudoElements[parameters.pseudoElement].properties = parameters.argument;
};
var properties = '''';
for (var property in parameters.argument) {
if (typeof parameters.argument[property] === ''function'')
parameters.element.pseudoElements[parameters.pseudoElement].properties[property] = parameters.argument[property]();
else
parameters.element.pseudoElements[parameters.pseudoElement].properties[property] = parameters.argument[property];
};
for (var property in parameters.element.pseudoElements[parameters.pseudoElement].properties) {
properties += property + '': '' + parameters.element.pseudoElements[parameters.pseudoElement].properties[property] + '' !important; '';
};
parameters.element.pseudoElements.styleSheet.addRule(selector, properties, parameters.element.pseudoElements[parameters.pseudoElement].index);
} else if (parameters.argument !== undefined && parameters.property !== undefined) {
if (!parameters.element.pseudoElements[parameters.pseudoElement].properties && !parameters.element.pseudoElements[parameters.pseudoElement].index) {
var newIndex = parameters.element.pseudoElements.styleSheet.rules.length || parameters.element.pseudoElements.styleSheet.cssRules.length || parameters.element.pseudoElements.styleSheet.length;
parameters.element.pseudoElements[parameters.pseudoElement].index = newIndex;
parameters.element.pseudoElements[parameters.pseudoElement].properties = {};
};
if (typeof parameters.property === ''function'')
parameters.element.pseudoElements[parameters.pseudoElement].properties[parameters.argument] = parameters.property();
else
parameters.element.pseudoElements[parameters.pseudoElement].properties[parameters.argument] = parameters.property;
var properties = '''';
for (var property in parameters.element.pseudoElements[parameters.pseudoElement].properties) {
properties += property + '': '' + parameters.element.pseudoElements[parameters.pseudoElement].properties[property] + '' !important; '';
};
parameters.element.pseudoElements.styleSheet.addRule(selector, properties, parameters.element.pseudoElements[parameters.pseudoElement].index);
};
} else if (parameters.argument !== undefined && parameters.property === undefined) {
var windowStyle = window.getComputedStyle(
parameters.element, ''::'' + parameters.pseudoElement
).getPropertyValue(parameters.argument);
if (parameters.element.pseudoElements) {
return parameters.element.pseudoElements[parameters.pseudoElement].properties[parameters.argument] || windowStyle;
} else {
return windowStyle || null;
};
} else {
console.error(''Invalid values!'');
return false;
};
};
Object.defineProperty(Element.prototype, ''styleBefore'', {
enumerable: false,
value: function(argument, property) {
return setPseudoElement({
element: this,
pseudoElement: ''before'',
argument: argument,
property: property
});
}
});
Object.defineProperty(Element.prototype, ''styleAfter'', {
enumerable: false,
value: function(argument, property) {
return setPseudoElement({
element: this,
pseudoElement: ''after'',
argument: argument,
property: property
});
}
});
})();
document.querySelector(''.element'').styleBefore(''content'', ''"New before!"'');
.element {
width: 480px;
margin: 0 auto;
border: 2px solid red;
}
.element::before {
content: ''Old before!'';
}
<div class="element"></div>
GitHub: https://github.com/yuri-spivak/managing-the-properties-of-pseudo-elements/
Si desea manipular los elementos de: antes o después de sudo completamente a través de CSS, puede hacerlo JS. Vea abajo;
jQuery(''head'').append(''<style id="mystyle" type="text/css"> /* your styles here */ </style>'');
Observe cómo el elemento <style>
tiene un ID, que puede usar para eliminarlo y adjuntarlo nuevamente si su estilo cambia dinámicamente.
De esta manera, su elemento es el estilo exactamente como lo quiere a través de CSS, con la ayuda de JS.
Siempre estoy agregando mi propia función de utils, que se ve así.
function setPseudoElContent(selector, value) {
document.styleSheets[0].addRule(selector, ''content: "'' + value + ''";'');
}
setPseudoElContent(''.class::after'', ''Hello World!'');
o hacer uso de las características de ES6:
const setPseudoElContent = (selector, value) => {
document.styleSheets[0].addRule(selector, `content: "${value}";`);
}
setPseudoElContent(''.class::after'', ''Hello World!'');
También podemos confiar en las propiedades (variables) personalizadas de CSS para manipular el pseudo-elemento. Podemos leer en la specification que:
Las propiedades personalizadas son propiedades ordinarias, por lo que se pueden declarar en cualquier elemento, se resuelven con la herencia normal y las reglas en cascada , se pueden condicionar con @media y otras reglas condicionales, se pueden usar en el atributo de estilo de HTML , se pueden leer o configurar utilizando el CSSOM , etc.
Teniendo en cuenta esto, la idea es definir la propiedad personalizada dentro del elemento y el pseudo-elemento simplemente la heredará; Así podemos modificarlo fácilmente.
Tenga en cuenta que las variables CSS pueden no estar disponibles en todos los navegadores que considere relevantes (por ejemplo, IE 11): https://caniuse.com/#feat=css-variables
1) Usando estilo en línea :
.box:before {
content:"I am a before element";
color:var(--color, red);
font-size:25px;
}
<div class="box"></div>
<div class="box" style="--color:blue"></div>
<div class="box" style="--color:black"></div>
<div class="box" style="--color:#f0f"></div>
2) Usando CSS y clases
.box:before {
content:"I am a before element";
color:var(--color, red);
font-size:25px;
}
.blue {
--color:blue;
}
.black {
--color:black;
}
<div class="box"></div>
<div class="box black" ></div>
<div class="box blue"></div>
3) Utilizando javascript
document.querySelectorAll(''.box'')[0].style.setProperty("--color", "blue");
document.querySelectorAll(''.box'')[1].style.setProperty("--color", "#f0f");
.box:before {
content:"I am a before element";
color:var(--color, red);
font-size:25px;
}
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
4) Usando jQuery
$(''.box'').eq(0).css("--color", "blue");
/* the css() function with custom properties works only with a jQuery vesion >= 3.x
with older version we can use style attribute to set the value. Simply pay
attention if you already have inline style defined!
*/
$(''.box'').eq(1).attr("style","--color:#f0f");
.box:before {
content:"I am a before element";
color:var(--color, red);
font-size:25px;
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
También se puede utilizar con valores complejos:
.box {
--c:"content";
--b:linear-gradient(red,blue);
--s:20px;
--p:0 15px;
}
.box:before {
content: var(--c);
background:var(--b);
color:#fff;
font-size: calc(2 * var(--s) + 5px);
padding:var(--p);
}
<div class="box"></div>
También puedes pasar el contenido al pseudo elemento con un atributo de datos y luego usar jQuery para manipular eso:
En HTML:
<span>foo</span>
En jQuery:
$(''span'').hover(function(){
$(this).attr(''data-content'',''bar'');
});
En CSS:
span:after {
content: attr(data-content) '' any other text you may want'';
}
Si desea evitar que aparezca el ''otro texto'', puede combinar esto con la solución de seucolega como esta:
En HTML:
<span>foo</span>
En jQuery:
$(''span'').hover(function(){
$(this).addClass(''change'').attr(''data-content'',''bar'');
});
En CSS:
span.change:after {
content: attr(data-content) '' any other text you may want'';
}
Una forma funcional pero no muy eficiente es agregar una regla al documento con el nuevo contenido y hacer referencia a ella con una clase. dependiendo de lo que se necesite, la clase podría necesitar una identificación única para cada valor en el contenido.
$("<style type=''text/css''>span.id-after:after{content:bar;}</style>").appendTo($("head"));
$(''span'').addClass(''id-after'');
Usted pensaría que esta sería una pregunta simple para responder, con todo lo que jQuery puede hacer. Desafortunadamente, el problema se reduce a un problema técnico: css: after y: before reglas no son parte del DOM, y por lo tanto no pueden modificarse utilizando los métodos DOM de jQuery.
Hay formas de manipular estos elementos utilizando JavaScript y / o CSS. el que uses depende de tus requerimientos exactos.
Voy a comenzar con lo que se considera ampliamente como el "mejor" enfoque:
1) Añadir / eliminar una clase predeterminada
En este enfoque, ya ha creado una clase en su CSS con un estilo diferente :after
o :before
. Coloque esta clase "nueva" más adelante en su hoja de estilo para asegurarse de que reemplaza:
p:before {
content: "foo";
}
p.special:before {
content: "bar";
}
Luego, puede agregar o eliminar esta clase fácilmente usando jQuery (o JavaScript de vainilla):
$(''p'').on(''click'', function() {
$(this).toggleClass(''special'');
});
$(''p'').on(''click'', function() {
$(this).toggleClass(''special'');
});
p:before {
content: "foo";
color: red;
cursor: pointer;
}
p.special:before {
content: "bar";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p>This is a paragraph.</p>
<p>This is another paragraph.</p>
- Pros: Fácil de implementar con jQuery; altera rápidamente múltiples estilos a la vez; impone la separación de preocupaciones (aislando su CSS y JS de su HTML)
- Contras: CSS debe estar escrito previamente, por lo que el contenido de
:before
o:after
no es completamente dinámico
2) Agregar nuevos estilos directamente a la hoja de estilo del documento
Es posible usar JavaScript para agregar estilos directamente a la hoja de estilo del documento, incluidos :after
y :before
estilos. jQuery no proporciona un atajo conveniente, pero afortunadamente el JS no es tan complicado:
var str = "bar";
document.styleSheets[0].addRule(''p.special:before'',''content: "''+str+''";'');
var str = "bar";
document.styleSheets[0].addRule(''p.special:before'', ''content: "'' + str + ''";'');
p:before {
content: "foo";
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p class="special">This is a paragraph</p>
<p>This is another paragraph</p>
.addRule()
y los .insertRule()
relacionados .insertRule()
están bien soportados hoy.
Como variación, también puede usar jQuery para agregar una hoja de estilo completamente nueva al documento, pero el código necesario no es un limpiador:
var str = "bar";
$(''<style>p.special:before{content:"''+str+''"}</style>'').appendTo(''head'');
var str = "bar";
$(''<style>p.special:before{content:"'' + str + ''"}</style>'').appendTo(''head'');
p:before {
content: "foo";
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p class="special">This is a paragraph</p>
<p>This is another paragraph</p>
Si estamos hablando de "manipular" los valores, no solo de agregarlos, también podemos leer el existente :after
o :before
estilos utilizando un enfoque diferente:
var str = window.getComputedStyle(document.querySelector(''p''), '':before'')
.getPropertyValue(''content'');
var str = window.getComputedStyle($(''p'')[0], '':before'').getPropertyValue(''content'');
console.log(str);
document.styleSheets[0].addRule(''p.special:before'', ''content: "'' + str+str + ''";'');
p:before {
content:"foo";
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p class="special">This is a paragraph</p>
<p>This is another paragraph</p>
Podemos reemplazar document.querySelector(''p'')
con $(''p'')[0]
cuando se usa jQuery, para un código ligeramente más corto.
- Pros: cualquier cadena se puede insertar dinámicamente en el estilo
- Contras: los estilos originales no se alteran, solo se anulan; el uso repetido (ab) puede hacer que el DOM crezca arbitrariamente grande
3) Modificar un atributo DOM diferente
También puede usar attr()
en su CSS para leer un atributo DOM particular. ( Si un navegador admite :before
, también es compatible con attr()
) . Al combinar esto con el content:
en algunos CSS preparados con cuidado, podemos cambiar el contenido (pero no otras propiedades, como el margen o el color) de :before
y :after
dinámicamente:
p:before {
content: attr(data-before);
color: red;
cursor: pointer;
}
JS:
$(''p'').on(''click'', function () {
$(this).attr(''data-before'',''bar'');
});
$(''p'').on(''click'', function () {
$(this).attr(''data-before'',''bar'');
});
p:before {
content: attr(data-before);
color: red;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p>This is a paragraph.</p>
<p>This is another paragraph.</p>
Esto se puede combinar con la segunda técnica si el CSS no se puede preparar antes de tiempo:
var str = "bar";
document.styleSheets[0].addRule(''p:before'', ''content: attr(data-before);'');
$(''p'').on(''click'', function () {
$(this).attr(''data-before'', str);
});
var str = "bar";
document.styleSheets[0].addRule(''p:before'', ''content: attr(data-before) !important;'');
$(''p'').on(''click'', function() {
$(this).attr(''data-before'', str);
});
p:before {
content: "foo";
color: red;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p>This is a paragraph.</p>
<p>This is another paragraph.</p>
- Pros: No crea infinitos estilos extra.
- Contras:
attr
en CSS solo se puede aplicar a cadenas de contenido, no a URL o colores RGB
$(''.span'').attr(''data-txt'', ''foo'');
$(''.span'').click(function () {
$(this).attr(''data-txt'',"any other text");
})
.span{
}
.span:after{
content: attr(data-txt);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class=''span''></div>
Alguien más comentó sobre agregar al elemento principal con un elemento de estilo completo y eso no es malo si solo lo haces una vez, pero si necesitas restablecerlo más de una vez, terminarás con un montón de elementos de estilo. Entonces, para evitar eso, creé un elemento de estilo en blanco en la cabeza con una identificación y reemplacé el HTML interno de esta manera:
<style id="pseudo"></style>
Entonces el JavaScript se vería así:
var pseudo = document.getElementById("pseudo");
function setHeight() {
let height = document.getElementById("container").clientHeight;
pseudo.innerHTML = `.class:before { height: ${height}px; }`
}
setHeight()
Ahora, en mi caso, lo necesitaba para establecer la altura de un elemento anterior según la altura de otro y cambiará al cambiar el tamaño, por lo que puedo usarlo setHeight()
cada vez que se cambie el tamaño de la ventana y la reemplazará <style>
correctamente.
Espero que eso ayude a alguien que estaba atascado tratando de hacer lo mismo.
Hice uso de las variables definidas en el :root
interior CSS
para modificar el pseudo-elemento:after
(lo mismo se aplica a :before
) , en particular para cambiar el valor de un estilo definido por y el valor de otro ( ) en la siguiente demo que genera colores aleatorios utilizando JavaScript. / jQuery:background-color
anchor
.sliding-middle-out:hover:after
content
anchor
#reference
demo
HTML
<a href="#" id="changeColor" class="sliding-middle-out" title="Generate a random color">Change link color</a>
<span id="log"></span>
<h6>
<a href="https://.com/a/52360188/2149425" id="reference" class="sliding-middle-out" target="_blank" title=" topic">Reference</a>
</h6>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.rawgit.com/davidmerfield/randomColor/master/randomColor.js"></script>
CSS
:root {
--anchorsFg: #0DAFA4;
}
a, a:visited, a:focus, a:active {
text-decoration: none;
color: var(--anchorsFg);
outline: 0;
font-style: italic;
-webkit-transition: color 250ms ease-in-out;
-moz-transition: color 250ms ease-in-out;
-ms-transition: color 250ms ease-in-out;
-o-transition: color 250ms ease-in-out;
transition: color 250ms ease-in-out;
}
.sliding-middle-out {
display: inline-block;
position: relative;
padding-bottom: 1px;
}
.sliding-middle-out:after {
content: '''';
display: block;
margin: auto;
height: 1px;
width: 0px;
background-color: transparent;
-webkit-transition: width 250ms ease-in-out, background-color 250ms ease-in-out;
-moz-transition: width 250ms ease-in-out, background-color 250ms ease-in-out;
-ms-transition: width 250ms ease-in-out, background-color 250ms ease-in-out;
-o-transition: width 250ms ease-in-out, background-color 250ms ease-in-out;
transition: width 250ms ease-in-out, background-color 250ms ease-in-out;
}
.sliding-middle-out:hover:after {
width: 100%;
background-color: var(--anchorsFg);
outline: 0;
}
#reference {
margin-top: 20px;
}
.sliding-middle-out:before {
content: attr(data-content);
display: attr(data-display);
}
JS / jQuery
var anchorsFg = randomColor();
$( ".sliding-middle-out" ).hover(function(){
$( ":root" ).css({"--anchorsFg" : anchorsFg});
});
$( "#reference" ).hover(
function(){
$(this).attr("data-content", "Hello World!").attr("data-display", "block").html("");
},
function(){
$(this).attr("data-content", "Reference").attr("data-display", "inline").html("");
}
);