People have often asked how they may write inline styles for pseudo classes. E.g.,
<a href="#" style=":hover: background: blue; :hover: color: white;">Hover Here</a>
So I got curious about what it'd take to make it happen. The most obvious solution was to use JavaScript to check for pseudo classes in an element's inline CSS. And then create an embedded stylesheet for any inline styles that have been detected.
I eventually landed on
const pseudoInlineStyles = {
enable: function (options) {
const defaultPseudoStyleTypes = ['active', 'focus', 'hover', 'visited', 'after', 'before', 'selected', 'first-child'];
const pseudoStyleTypes = options?.pseudoStyleTypes ? [...defaultPseudoStyleTypes, ...options.pseudoStyleTypes] : defaultPseudoStyleTypes;
const cssRules = [];
// Iterate through the pseudo style types
pseudoStyleTypes.forEach((pseudoStyleType) => {
// Find elements with the specified pseudo style
const elementsWithPseudoStyle = document.querySelectorAll(`[style*="${pseudoStyleType}"]`);
// Loop through matching elements
elementsWithPseudoStyle.forEach((element) => {
const elementName = element.tagName.toLowerCase();
const elementId = element.id ? `#${element.id}` : '';
const elementClasses = element.className ? `.${element.className.split(' ').join('.')}` : '';
const elementSelector = `${elementName}${elementId}${elementClasses}`;
// Extract the inline style for the pseudo-class
const elementInlineStyle = element.getAttribute('style');
const pseudoStyleRegex = new RegExp(`:${pseudoStyleType}:(.*?);`, 'gi');
// Match the pseudo style definition
const pseudoStyleMatches = elementInlineStyle.match(pseudoStyleRegex);
if (pseudoStyleMatches) {
// Loop through the matches
pseudoStyleMatches.forEach((pseudoStyleMatch) => {
// Extract the pseudo style definition
const pseudoStyleDefinition = pseudoStyleMatch.replace(`:${pseudoStyleType}:`, '');
// Create the CSS rule
const cssRuleForPseudoStyle = `${elementSelector}:${pseudoStyleType} { ${pseudoStyleDefinition.trim()}; }`;
cssRules.push(cssRuleForPseudoStyle);
});
}
});
});
// Insert all the collected CSS rules into a style element
if (cssRules.length > 0) {
const styleSheet = document.getElementById('pseudo-inline-css');
if (styleSheet) {
styleSheet.innerHTML = cssRules.join('\n');
} else {
const newStyleSheet = document.createElement('style');
newStyleSheet.id = 'pseudo-inline-css';
newStyleSheet.innerHTML = cssRules.join('\n');
document.head.appendChild(newStyleSheet);
}
}
},
};
And that allowed me write
<html lang="en">
<head>
<script src="https://cdn.jsdelivr.net/gh/dara-tobi/pseudo-inline-styles@1.0.1/src/pseudo-inline-styles.js"></script>
<title>PseudoInlineStyles Demo</title>
</head>
<body>
<a href="#" id="primary-link" class="button large" style="
:after: content: ' SOFTWARE';
:focus: text-decoration: underline !important;
:hover: background-color: red !important;
:hover: color: black !important;
text-decoration: none;
color:white;
background-color: #005493;
font-size: 1.5rem;
text-align: center;
padding: 20px;">12 HANDS </a>
<script>pseudoInlineStyles.enable({pseudoStyleTypes: ['focus-within', 'last-child']});</script>
</body>
</html>
If you're curious to see a live demo, check it out here.
And if you want to take it for a spin, check out the Github repo.
Caveats of using this approach are
i. for each inline pseudo class, you get an Unknown property name
error when inspecting the element's styles in dev tools.
ii. you get squiggly lines in your code editor because this isn't the standard syntax for writing inline styles.
Top comments (0)