- CSS selector simplifier regular expression in JavaScript
- The Solution
- Extra; About regexes
- Регулярные выражения в CSS-селекторах и GTM
- CSS Regex selector — Using Regular Expression in CSS
- Selecting on Attribute and value
- Applying CSS with Pseudo-class :not
- Regex for css selector
- One Yes, CSS also has regularities (Amen)
- Two general rules of regular expressions
- Three CSS attribute selectors and regular expressions
CSS selector simplifier regular expression in JavaScript
I’m working on a project where it needs to evaluate CSS as a string. Basically, it compares CSS selectors against a DOM to see if the CSS selector is used in the DOM.
But CSS has pseudo classes. A common one a lot of people are familiar with is: a:hover < text-decoration: crazy >. So that :hover part is not relevant when evaluating the CSS selector against the DOM. So you chop off the :hover bit and is left with a which you can then look for in the DOM.
But there are some tricks and make this less trivial. Consider, this from Bootstrap 3
a[href^="#"]:after, a[href^="javascript:"]:after content: ""; >
In this case we can’t simply split on a : character.
Another non-trivial example comes from Semantic UI:
.ui[class*="4:3"].embed padding-bottom: 75%; > .ui[class*="16:9"].embed padding-bottom: 56.25%; > .ui[class*="21:9"].embed padding-bottom: 42.85714286%; >
Basically, if you just split the selectors (e.g. a:hover ) on the first : and keep everything to the left (e.g. a ), with these non-trivial CSS selectors you’d get this:
etc. These CSS selectors will fail. Both Firefox and Chrome seem to swallow any errors but cheerio will raise a SyntaxError and not just that but the problem is that the CSS selector is just the wrong one to look for.
The Solution
The solution has to be to split by the : character when it’s not between two quotation marks.
This Stackoverflow post helped me with the regex. It was trivial to extend now my final solution looks like this:
/** * Reduce a CSS selector to be without any pseudo class parts. * For example, from 'a:hover' return 'a'. And from 'input::-moz-focus-inner' * to 'input'. * Also, more advanced ones like 'a[href^="javascript:"]:after' to * 'a[href^="javascript:"]'. * The last example works too if the input was 'a[href^='javascript:']:after' * instead (using ' instead of "). * * @param selector * @return */ const reduceCSSSelector = selector => return selector.split( /:(?=([^"'\\]*(\\.|["']([^"'\\]*\\.)*[^"'\\]*['"]))*[^"']*$)/g )[0] >
Extra; About regexes
I’ve been coding for about 20 years and would like to think I know my way around writing regular expressions in various languages. However, I’m also eager to admit that I often fumble and rely on googling/stackoverflow more than actually understanding what the heck I’m doing. That’s why I found this comment so amusing:
Thank you! Didn’t think it was possible. I understand 100% of the theory, about 60% of the regex, and I’m down to 0% when it comes to writing it on my own. Oh, well, maybe one of these days. – Azmisov
Регулярные выражения в CSS-селекторах и GTM
В предыдущих материалах я описывал работу CSS-селекторов и селекторов в jQuery, отдельно останавливаясь на такой теме, как селекторы атрибутов. В этой статье хочу более подробно разобрать регулярные выражения, которые можно использовать при составлении CSS-селекторов.
- селектор — это часть CSS-правила, которая сообщает браузеру, к какому элементу (или элементам) веб-страницы будет применен стиль;
- регулярные выражения — инструмент для поиска строк и их проверки на соответствие какой-либо конструкции. Результатом применения регулярного выражения является подмножество данных, отобранное согласно логике, заложенной в выражении.
- у HTML-элементов на странице могут быть атрибуты — дополнительные значения, которые настраивают элементы или регулируют их поведение различным способом, чтобы соответствовать критериям пользователей;
- CSS-селекторы применяются в Google Tag Manager для условий активации триггеров, а также в пользовательских переменных.
Чтобы узнать какой CSS-селектор у элемента, необходимо открыть панель разработчика (в Google Chrome клавиша F12) и:
- переключиться на вкладку Elements;
- нажать на кнопку инспекции элемента;
- выбрать элемент, у которого хотим определить CSS-селектор;
- после этого кликнуть правой кнопкой мыши на тот элемент, который подсветился на вкладке Elements;
- выбрать Copy — Copy selector (6):
Определение CSS-селектора у элемента на странице
В результате мы получим значение CSS-селектора. Например, такого вида:
Верно и обратное. Зная CSS-селектор элемента, мы можем с помощью расширения CSS Selector Tester найти его на странице. Введя значение в соответствующем поле, расширение подсветит его:
Это дает нам возможность понять, встречается ли где-нибудь еще элемент с таким же CSS-селектором на странице. Или же он является уникальным. Если такой элемент на странице не один, а целая группа, CSS Selector Tester выделит красным пунктирным прямоугольником все встречающиеся на странице элементы. Помимо этого в CSS-селекторах можно использовать регулярные выражения. Если быть точнее, то с помощью специальной конструкции (спецсимволов) вы можете задать определенное правило, которое будет распространяться на атрибут не одного элемента, а сразу на целую группу, которая попадает под заданное условие. Давайте разберем практическую задачу. На сайте по производству мебели необходимо отслеживать клик по адресу магазина и передавать эту информацию в инструменты веб-аналитики.
Клик по адресу — Отправка события в аналитику
События в Google Analytics
Чтобы мы делали в обычной ситуации? Определяли бы для каждого элемента свой CSS-селектор и настраивали бы триггер с конкретным условием, а потом еще и собственный тег для передачи данных в Яндекс.Метрику и Google Analytics. В результате у нас бы получилось много триггеров и много тегов. Нам это не подходит. Если мы исследуем каждый из этих элементов, то найдем закономерность — все они имеют одинаковое начало атрибута id вида store-span-.
У всех элементов одинаковое начало store-span-
Далее отличается только цифра: 69, 86, 77, 78, 85 и т.д. Чтобы отследить клики по всем таким адресам, нам в GTM потребуется прописать всего лишь 1 условие для триггера, используя регулярные выражения, и создать 1 тег. У маркетологов часто встречается схожая задача — отследить клик по кнопке Купить или Добавить в корзину. Товаров может быть много, у каждого из них своя кнопка, в которой отличие только в ее идентификаторе, классе, атрибуте:
Кнопка «Купить» с одинаковым атрибутом
CSS Regex selector — Using Regular Expression in CSS
Just like JQuery, CSS also offer a great way to filter out elements with selectors using Regular Expressions.
Selecting on Attribute and value
[[att=str]] :- attribute value is exactly matching to str [[att*=str] ]:- attribute value contains str — value can contain str anywhere either in middle or at end. [att] :- Elements which contain attribute att with any valueApplying CSS with Pseudo-class :not
This quite interesting using :not selector to filter out on element properties. Using not selector you can distinguish them from other elements. In this selector also you can use regular expressions to find your elements.
input:not([DISABLED]) background-color: yellow; >
The Geeky Way is founded by Sanyam Khurana. He graduated from Georgia Tech, Atlanta, US with a Master’s degree in Computer Science. He goes by ‘CuriousLearner’ all over the web & has spoken at many international conferences. He likes to contribute to FOSS. He is listed as an individual contributor of the Django project, bug-triager for CPython & has his name listed in the credits section of every browser ever released by Mozilla. In his free time, he likes to improve his guitar skills or binge-watch series.. You can find him on Twitter
Posted on: Wed 01 January 2014
Regex for css selector
Put a head picture to relax
One Yes, CSS also has regularities (Amen)
CSS is loaded with two powerful tools: matrix and regular.
In fact, we don’t have to be surprised, CSS is also a language after all, and regularity is inherently beneficial to something outside of a specific language.
Two general rules of regular expressions
Regardless of the language, the rules of regular expressions are universal, and the difference may lie in the form of writing.
Regex is a very deep topic. If you really want to talk about it, you can write a thick book! It’s hard to remember, like when I want to use Baidu.
Among them, some key characters have specific meanings and represent the rules of the regular expression world.
- The character ^ means that the starting position of the string matches;
- The character $ means the end position of the string matches;
- The character * means that the string matches anywhere;
- The character i means that string matching is not case-sensitive;
- The character g represents a string global match;
These rules are also common in the CSS world.
Three CSS attribute selectors and regular expressions
The development of CSS attribute selectors is currently divided into 3 stages:
- CSS2.1 attribute selector
Direct match: [attr], [attr=”val”], [attr~=”val”], [attr|=”bar”] - CSS3 attribute selector
Regular matching: [foo^=”bar”], [foo$=”bar”], [foo*=”bar”] - CSS4 attribute selector
Ignore case matching: [attr=”val” i]
Among them, the latter two stages belong to the regular matching stage. With the development of CSS, more complex regular matching should appear, and we can wait and see.
So what is the meaning of so many attribute matching words?
As long as the element has the attribute of attr:
div attr="val"> div> div attr="text val"> div> div attr="value"> div> div attr="val-ue"> div>
div attr="val"> div> div attr="text val"> div> div attr="value"> div> div attr="val-ue"> div>
The value of’attr’ must contain the word’val’. Note that the wording here is «word» instead of characters. CSS was invented by a foreigner. The native language of the foreigner is English, and English sentences are all implemented by one word + space + one word . therefore:
div attr="val"> div> div attr="text val"> div> div attr="value"> div> div attr="val-ue"> div>
At the time of CSS2.1, CSS did not consider the languages of other countries so deeply. Therefore, the usage of matching «words» like this is only useful for characters in the ASCII range. For Chinese, even if you put a space in the middle of Chinese and pretend to be a «word», it is useless. therefore:
[attr~="I"] div attr="I'm so handsome and ruthless">div>
The attr’ attribute value must start with the word bar, or start with bar-. Similarly, it is a «word», not a «character», so there are:
div attr="bar"> div> div attr="bar-val"> div> div attr="barval"> div> div attr="bar val"> div>
Similarly, Chinese is not supported. To support Chinese, please use CSS3 attribute selector.
Several attribute selectors of the above CSS2.1 are supported from IE7 browser. However, IE7 browser is not strictly supported.
The first three characters of the value need to be val, so:
div attr="val"> div> div attr="text val"> div> div attr="value"> div> div attr="val-ue"> div>
Compare the above [attr|=”bar”] to feel the difference between «word» and «character».
The last three characters of the attribute value need to be val, so, therefore:
div attr="val"> div> div attr="text val"> div> div attr="value"> div> div attr="val-ue"> div>
The three characters val can be included anywhere in the attribute value, so:
div attr="val"> div> div attr="text val"> div> div attr="value"> div> div attr="val-ue"> div>
The above three attribute selectors belong to CSS3, but it is amazing that IE7 browser also supports them. Just like the IE8 browser supports CSS3 box-sizing, this feeling is like that Xiao Ming, who usually takes 38 points on the test, suddenly got 61 points on the test. Is it unexpected or pleasant surprise?
Last heavyweight guest, the attribute value is case-insensitive i:
For example: [attr~=”val” i], [attr*=”val” I], etc. are all legal writing. Among them, i can also use capital I.
is the same as the i in regular expressions, ignoring case. Since languages like Chinese do not have the concept of case, this feature is only for characters in the ASCII range.
We can give a simple example to compare, the existing selector [attr*=”val”], then:
div attr="VAL"> div> div attr="Text val"> div> div attr="Value"> div> div attr="Val-ue"> div>
However, if there is more i, code>[attr*=”val” i], then:
div attr="VAL"> div> div attr="Text val"> div> div attr="Value"> div> div attr="Val-ue"> div>
No matter the case, it can be matched.
compatibility
Currently Chrome, FireFox, Safari already support i regular, but after IE surprise, it is back to its original shape, including IE14, it has not yet supported case insensitivity:
It is estimated that this feature can be applied in actual projects soon.
Instance
Seeing is believing. Regarding the regular expression of selectors, I made a simple demo. You can click here: CSS selector regular expression demo
li[data-index^='t'] < color: red; > li[data-index^='f'] < color: blue; > li[data-index^='f' i]:after < content: '✓Support i regular'; color: green; >
The result is in the FireFox browser: