Search code examples
cssqueryselector

Is there a reliable selector that can select elements based on styles?


Here is a function I have written. It works well to get the closest element that has a certain attribute:

// Example of attribute if id

export function getClosestAttribute(
  element: SVGElement,
  attribute: keyof typeof svgAttributeToCssStyle,
  excludeElement: boolean
): string | null {
  let firstIncludedEl: Element | null = element;
  if (excludeElement) {
    firstIncludedEl = element.parentElement;
  }
  if (!firstIncludedEl) {
    return null;
  }
  const closestEl = firstIncludedEl.closest(`[${attribute}]`);
  if (!closestEl) {
    return null;
  }

  return closestEl.getAttribute(attribute);
}

Is it possible to write something similar for styles? E.g. I want to select any elements that have style="...fill:..."?


Solution

  • Update

    Another approach is to match two rules. The first "start with" rule matches: color: red, but not background-color: red.

    div[style^="color:"] {
      text-decoration: underline;
    }
    

    The second rule matches when the string occurs anywhere later in the style value:

    div[style*=" color:"] {
      text-decoration: underline;
    }
    

    Then we just chain them together:

    div[style^="color:"],
    div[style*=" color:"] {
      text-decoration: underline;
      opacity: 0.5;
    }
    <div style="background-color: red;">Should not match
    </div>
    
    <div style="font-size: 20px; color: red;">Match
    </div>
    
    <div style="color: red; font-size: 32px;">Match
    </div>
    
    <div style="font-size: 20px; background-color: red;">Should not match
    </div>

    __

    You could use an attribute selector and look for a style value that contained a string of your choosing. However, white space matters. If you're looking for style*="color: red" but your style value has no space between color: and red, the selector will not find matches.

    [attr*=value] Represents elements with an attribute name of attr whose value contains at least one occurrence of value within the string.

    Example:

    div[style*="color: red"] {
      text-decoration: underline;
    }
    <div style="color: blue;">Regular div
    </div>
    
    <div style="color: red;">Add an underline
    </div>