Selecting and manipulating CSS pseudo-elements such as ::before and ::after using jQuery
有没有任何方式来选择/操控CSS伪元素(如
例如,我的样式表有以下规则:
1 | .span::after{ content:'foo' } |
Mi-24变更"foo""酒吧使用jQuery?
您还可以将内容传递给具有数据属性的伪元素,然后使用jquery来操作:
在HTML中:
1 | <span>foo</span> |
在jQuery中:
1 2 3 | $('span').hover(function(){ $(this).attr('data-content','bar'); }); |
在CSS中:
1 2 3 | span:after { content: attr(data-content) ' any other text you may want'; } |
如果要防止"其他文本"出现,可以将其与Seucolega的解决方案结合起来,如下所示:
在HTML中:
1 | <span>foo</span> |
在jQuery中:
1 2 3 | $('span').hover(function(){ $(this).addClass('change').attr('data-content','bar'); }); |
在CSS中:
1 2 3 | span.change:after { content: attr(data-content) ' any other text you may want'; } |
您可能会认为这是一个简单的问题要回答,jquery可以做的其他一切。不幸的是,问题归结为一个技术问题:css:after和:before规则不属于DOM,因此不能使用jquery的DOM方法更改规则。
有一些方法可以使用javascript和/或css解决方案来操作这些元素;您使用哪种解决方案取决于您的确切需求。
我将从广泛认为的"最佳"方法开始:
1)添加/删除预定类别在这种方法中,您已经使用不同的
1 2 3 4 5 6 | p:before { content:"foo"; } p.special:before { content:"bar"; } |
然后您可以使用jquery(或普通的javascript)轻松地添加或删除这个类:
1 2 3 | $('p').on('click', function() { $(this).toggleClass('special'); }); |
1 2 3 | $('p').on('click', function() { $(this).toggleClass('special'); }); |
1 2 3 4 5 6 7 8 | p:before { content:"foo"; color: red; cursor: pointer; } p.special:before { content:"bar"; } |
1 2 3 4 5 6 7 8 | <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"> <p> This is a paragraph. </p> <p> This is another paragraph. </p> |
- 优点:易于使用jquery实现;一次快速改变多种样式;强制分离关注点(将CSS和JS与HTML隔离)
- 缺点:CSS必须预先编写,所以
:before 或:after 的内容不是完全动态的
2)直接在文档样式表中添加新样式
可以使用javascript直接向文档样式表添加样式,包括
1 2 | var str ="bar"; document.styleSheets[0].addRule('p.special:before','content:"'+str+'";'); |
1 2 | var str ="bar"; document.styleSheets[0].addRule('p.special:before', 'content:"' + str + '";'); |
1 2 3 4 | p:before { content:"foo"; color: red; } |
1 2 3 4 5 6 7 | <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"> <p class="special">This is a paragraph </p> <p> This is another paragraph </p> |
目前,
作为一种变体,您也可以使用jquery向文档中添加一个全新的样式表,但所需的代码并不干净:
1 2 | var str ="bar"; $('<style>p.special:before{content:"'+str+'"}</style>').appendTo('head'); |
1 2 | var str ="bar"; $('<style>p.special:before{content:"' + str + '"}</style>').appendTo('head'); |
1 2 3 4 | p:before { content:"foo"; color: red; } |
1 2 3 4 5 6 7 | <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"> <p class="special">This is a paragraph </p> <p> This is another paragraph </p> |
如果我们谈论的是"操纵"这些值,而不仅仅是添加这些值,我们还可以使用不同的方法读取现有的
1 2 | var str = window.getComputedStyle(document.querySelector('p'), ':before') .getPropertyValue('content'); |
1 2 3 4 | var str = window.getComputedStyle($('p')[0], ':before').getPropertyValue('content'); console.log(str); document.styleSheets[0].addRule('p.special:before', 'content:"' + str+str + '";'); |
1 2 3 4 | p:before { content:"foo"; color: red; } |
1 2 3 4 5 6 7 | <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"> <p class="special">This is a paragraph </p> <p> This is another paragraph </p> |
在使用jquery时,我们可以用
- 优点:任何字符串都可以动态插入样式
- 缺点:原始样式没有改变,只是被重写;重复使用(ab)可以使dom任意增大
3)更改不同的dom属性
也可以在CSS中使用
1 2 3 4 5 | p:before { content: attr(data-before); color: red; cursor: pointer; } |
JS:
1 2 3 | $('p').on('click', function () { $(this).attr('data-before','bar'); }); |
1 2 3 | $('p').on('click', function () { $(this).attr('data-before','bar'); }); |
1 2 3 4 5 | p:before { content: attr(data-before); color: red; cursor: pointer; } |
1 2 3 4 5 6 7 8 | <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"> <p> This is a paragraph. </p> <p> This is another paragraph. </p> |
如果不能提前准备好CSS,可以将其与第二种技术结合起来:
1 2 3 4 5 6 7 | var str ="bar"; document.styleSheets[0].addRule('p:before', 'content: attr(data-before);'); $('p').on('click', function () { $(this).attr('data-before', str); }); |
1 2 3 4 5 6 | var str ="bar"; document.styleSheets[0].addRule('p:before', 'content: attr(data-before) !important;'); $('p').on('click', function() { $(this).attr('data-before', str); }); |
1 2 3 4 5 | p:before { content:"foo"; color: red; cursor: pointer; } |
1 2 3 4 5 6 7 8 | <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"> <p> This is a paragraph. </p> <p> This is another paragraph. </p> |
- 优点:不会创造无限的额外风格
- 缺点:CSS中的
attr 只能应用于内容字符串,不能应用于URL或RGB颜色。
尽管浏览器通过CSS呈现这些元素,就好像它们与其他真实的DOM元素一样,但伪元素本身并不属于DOM,因为顾名思义,伪元素不是真实的元素,因此不能直接使用jquery(或任何与此相关的javascript API,甚至不能使用selec)来选择和操作它们。Tor API)。这适用于您试图用脚本修改其样式的任何伪元素,而不仅仅是
您只能在运行时通过cssom(想想
但是,您总是可以找到其他方法,例如:
将样式应用于一个或多个任意类的伪元素,然后在类之间切换(参见Seucolega的快速示例答案)-这是惯用的方法,因为它使用简单的选择器(伪元素不是)来区分元素和元素状态,以及它们的使用方式。
通过修改文档样式表来操纵应用于所述伪元素的样式,这更像是一种黑客行为。
不能在jquery中选择伪元素,因为它们不是dom的一部分。但是您可以向父元素添加一个特定的类,并在CSS中控制它的伪元素。
例子
在jQuery中:
1 2 | <script type="text/javascript"> $('span').addClass('change'); |
在CSS中:
1 | span.change:after { content: 'bar' } |
按照克里斯蒂安的建议,你也可以:
1 | $('head').append("<style>.span::after{ content:'bar' }</style>"); |
我们也可以依赖自定义属性(也就是CSS变量)来操作伪元素。我们可以在说明书中看到:
Custom properties are ordinary properties, so they can be declared on
any element, are resolved with the normal inheritance and cascade
rules, can be made conditional with @media and other conditional rules, can be used in HTML’s style attribute, can be read or set using the CSSOM, etc.
考虑到这一点,我们的想法是在元素中定义自定义属性,而伪元素将简单地继承它;因此我们可以很容易地修改它。
请注意,CSS变量可能不适用于您认为相关的所有浏览器(例如,IE 11):https://canius.com/feat=css变量
1)使用内联样式:
1 2 3 4 5 | .box:before { content:var(--content,"I am a before element"); color:var(--color, red); font-size:25px; } |
1 |
2)使用CSS和类
1 2 3 4 5 6 7 8 9 10 11 12 13 | .box:before { content:var(--content,"I am a before element"); color:var(--color, red); font-size:25px; } .blue { --color:blue; --content:'I am a blue element'; } .black { --color:black; } |
1 |
3)使用javascript
1 2 | document.querySelectorAll('.box')[0].style.setProperty("--color","blue"); document.querySelectorAll('.box')[1].style.setProperty("--content","'I am another element'"); |
1 2 3 4 5 | .box:before { content:var(--content,"I am a before element"); color:var(--color, red); font-size:25px; } |
1 |
4)使用jQuery
1 2 3 4 5 6 | $('.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"); |
1 2 3 4 5 | .box:before { content:"I am a before element"; color:var(--color, red); font-size:25px; } |
1 | <script src="https://code.jquery.com/jquery-3.3.1.min.js"> |
它还可以与复杂值一起使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | .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); } |
1 |
您可能会注意到,我考虑的语法是
从相同的规范中,我们可以看到:
The value of a custom property can be substituted into the value of another property with the var() function. The syntax of var() is:
var() = var( [, ]? ) The first argument to the function is the name of the custom property to be substituted. The second argument to the function, if provided, is a fallback value, which is used as the substitution value when the referenced custom property is invalid.
后来:
To substitute a var() in a property’s value:
If the custom property named by the first argument to the var() function is animation-tainted, and thevar() function is being used in the animation property or one of its longhands, treat the custom property as having its initial value for the rest of this algorithm.If the value of the custom property named by the first argument to the var() function is anything but the initial value, replace thevar() function by the value of the corresponding custom property.Otherwise, if the var() function has a fallback value as its second argument, replace thevar() function by the fallback value. If there are anyvar() references in the fallback, substitute them as well.Otherwise, the property containing the var() function is invalid at computed-value time.
如果不设置自定义属性,或者将其设置为
相关的
如何将继承值存储在CSS自定义属性(又称CSS变量)中?
框模型的CSS自定义属性(变量)
以下是访问CSS中定义的样式属性:在样式属性之后和之前:
1 2 3 4 5 6 7 8 9 | // 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'); |
如果您想完全通过css操作sudo元素的::before或::after,可以使用js。见下文;
1 | jQuery('head').append('<style id="mystyle" type="text/css"> /* your styles here */ </style>'); |
请注意,
");
谢谢大家!我做了我想做的:D网址:http://jsfiddle.net/tfc9j/42/给你看看
我想让外部DIV的不透明度不同于内部DIV的不透明度,并通过单击somwewhere;)进行更改。谢谢!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | $('#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%; } <p> ena p </p> <p id="duop">duoyyyyyyyyyyyyyy p </p> |
这是不实际的,因为我写这篇文章并不是为了现实世界的需要,只是为了给你一个可以实现的例子。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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>"); } } } |
当前添加的a/或附加一个样式元素,该元素包含您所需的属性,这些属性将影响目标元素后面的伪元素。
这个可以用作
1 | css.after("someElement"," content: 'Test'; position: 'absolute';") // editing / adding styles to :after |
和
1 | css.before( ... ); // to affect the before pseudo element. |
和after:and before:pseudo元素一样,不能通过dom直接访问,目前无法自由编辑css的特定值。
我的方法只是一个例子,它不适合实践,你可以修改它,尝试一些你自己的技巧,使它适合真实世界的使用。
所以,用这个和其他方法做你自己的实验吧!
谨致问候-阿达尔什·赫格德。
当你只需要在head上附加一个
1 | $('head').append('<style>.span:after{ content:'changed content' }</style>') |
我总是添加我自己的utils函数,看起来是这样的。
1 2 3 4 5 | function setPseudoElContent(selector, value) { document.styleSheets[0].addRule(selector, 'content:"' + value + '";'); } setPseudoElContent('.class::after', 'Hello World!'); |
或利用ES6功能:
1 2 3 4 5 | const setPseudoElContent = (selector, value) => { document.styleSheets[0].addRule(selector, `content:"${value}";`); } setPseudoElContent('.class::after', 'Hello World!'); |
您可以创建一个伪属性或使用现有属性,并在伪元素的样式表中继承它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | .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%; } |
1 | <span id="arrow" class="arrow"></span> |
它似乎不适用于"内容"属性:(
我已经创建了一个jquery插件来添加CSS伪规则,比如对特定元素使用
- 插件代码和测试用例在这里
- 将用例作为简单的CSS图像弹出窗口显示在此处
用途:
1 2 3 4 5 6 7 8 9 10 11 12 | $('body') .css({ backgroundColor: 'white' }) .cssPseudo('after', { content: 'attr(title)", you should try to hover the picture, then click it."', position: 'absolute', top: 20, left: 20 }) .cssPseudo('hover:after', { content: '"Now hover the picture, then click it!"' }); |
这里有很多答案,但没有一个答案可以帮助操纵
我建议这样做。假设您的HTML如下所示:
1 | Test |
然后,在css中设置它的:before,并将其设计为:
1 2 3 4 5 6 7 8 | #something:before{ content:"1st"; font-size:20px; color:red; } #something{ content:'1st'; } |
请注意,我在元素本身中也设置了
在某个类
1 2 3 4 | .activeS:before{ color:green !important; font-size:30px !important; } |
现在,您可以通过将类添加到:before元素来更改:before样式,如下所示:
1 2 3 4 5 | <button id="changeBefore">Change</button> $('#changeBefore').click(function(){ $('#something').addClass('activeS'); }); |
如果您只想获取EDOCX1[1]的内容,可以这样做:
1 2 3 4 5 | <button id="getContent">Get Content</button> $('#getContent').click(function(){ console.log($('#something').css('content'));//will print '1st' }); |
最后,如果您希望通过jquery动态地更改
1 2 3 4 5 6 7 | <button id="changeBefore">Change</button> var newValue = '22';//coming from somewhere var add = '<style>#something:before{content:"'+newValue+'"!important;}</style>'; $('#changeBefore').click(function(){ $('body').append(add); }); |
单击上面的"changebefore"按钮,将
我希望它有帮助。
1 2 3 4 | $('.span').attr('data-txt', 'foo'); $('.span').click(function () { $(this).attr('data-txt',"any other text"); }) |
1 2 3 4 5 | .span{ } .span:after{ content: attr(data-txt); } |
1 | <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"> |
你可以使用我的插件。
jQuery:
16
1 2 3 4 5 6 7 8 9 | .element { width: 480px; margin: 0 auto; border: 2px solid red; } .element::before { content: 'Old before!'; } |
1 | <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"> |
应该指定这些值,如jquery.css的常规函数中所示。
此外,还可以获取伪元素参数的值,如jquery.css的常规函数:
1 | console.log( $(element).cssBefore(parameter) ); |
JS:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | (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!"'); |
1 2 3 4 5 6 7 8 9 | .element { width: 480px; margin: 0 auto; border: 2px solid red; } .element::before { content: 'Old before!'; } |
1 |
github:https://github.com/yuri-spivak/managing-the-properties-of-pseudo-elements/
有人评论说要用一个完整的样式元素附加到head元素,如果你只做一次,那也不错,但是如果你需要多次重设它,你最终会得到大量的样式元素。为了防止我在头部创建了一个带有ID的空白样式元素,并像这样替换它的innerhtml:
1 | <style id="pseudo"></style> |
然后,javascript将如下所示:
1 2 3 4 5 6 7 8 | var pseudo = document.getElementById("pseudo"); function setHeight() { let height = document.getElementById("container").clientHeight; pseudo.innerHTML = `.class:before { height: ${height}px; }` } setHeight() |
现在,在我的例子中,我需要它来根据另一个元素的高度设置before元素的高度,并且它会随着调整大小而改变,所以使用它,我可以在每次调整窗口大小时运行