Enabling inline CSS for pseudo classes
Tags: javascript, css, frontend, hacks
Published: 2023-10-17 23:58:35

People have often asked how they may write inline styles for pseudo classes. E.g.,

```html
<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

```javascript
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
<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](https://jsfiddle.net/dara_tobi/3u80grm4/11/), check it out [here](https://jsfiddle.net/dara_tobi/3u80grm4/11/).

And if you want to take it for a spin, check out the [Github repo](https://github.com/dara-tobi/pseudo-inline-styles).

**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.

![Screenshot of unknown-property-name errors that show up when inspecting the styles of an element with inline pseudo classes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2hpropazy6jlgohm5ckr.png)

ii. you get squiggly lines in your code editor because this isn't the standard syntax for writing inline styles.

![Screenshot of VS Code showing squiggly lines under the inline pseudo classes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gsxip9cbipdd0nhh4d8m.png)