15

Is there a way to select all custom elements with CSS? I want to make all custom elements block elements by default (most browsers make them inline by default), and then override this as necessary.

My rule may look something like this:

*::custom {
    display: block;
}

All custom elements have dashes in the standard, so I could create a rule taking advantage of that, but it would be slower on many/most current browsers, as it would need to use regular expressions. If there were a built-in selector, this would probably be faster.

13
  • 1
    So how many custom elements do you have in your project? 5, 10, 20? It's simpler just write rules manually and forget about it: x-one, x-two, ..., x-xxx {display: block;}. Commented Jul 17, 2015 at 17:00
  • 1
    AFAIK, there is no such pseudoselector, nor does CSS support partially wildcarded names in the selectors (though it is an obvious enhancement). Commented Jul 17, 2015 at 17:02
  • 1
    "Most browsers make them inline by default": that's because the initial value of display is inline. Commented Jul 17, 2015 at 17:05
  • Can you not add class or data- attributes? Commented Jul 17, 2015 at 17:06
  • @divinecomedian, As the Angular documentation says (this relates to directives, but can also apply to elements/attributes, as that is what directives are): "Use an element when you are creating a component that is in control of the template. The common case for this is when you are creating a Domain-Specific Language for parts of your template. Use an attribute when you are decorating an existing element with new functionality." Commented Jul 17, 2015 at 18:04

7 Answers 7

7

No, there isn't a pseudo selector to do that.

One certainly not optimal solution, however, would be to use this type of CSS:

:not(html, head, body, h1, h2, h3, h4, h5, h6, div, ...) {
  /* Code here */
}

It would work! On the down side if ever new elements are added you need to add that element into your not-selector. Yay.

^.^

Sign up to request clarification or add additional context in comments.

Comments

4

Add an inert custom attribute to your custom elements:

<some-element cutom-elem /> <other-element custom-elem />
<script> 
  var customs = document.querySelectorAll( "*[custom-elem]" )
</script>
<style>
    *[custom-elem] { display: block ; }
</style>

1 Comment

This could work (though I would put data- at the beginning of the custom attribute), and is similar to what I was doing. Now I removed many custom elements because I realized some built-in elements are OK. I would just rather not add more attributes than I have to.
3

Here's a workaround based on Florrie's answer: :not(html):not(head):not(title):not(base):not(link):not(meta):not(style):not(body):not(article):not(section):not(nav):not(aside):not(h1):not(h2):not(h3):not(h4):not(h5):not(h6):not(hgroup):not(header):not(footer):not(address):not(p):not(hr):not(pre):not(blockquote):not(ol):not(ul):not(li):not(dl):not(dt):not(dd):not(figure):not(figcaption):not(div):not(main):not(a):not(em):not(strong):not(small):not(s):not(cite):not(q):not(dfn):not(abbr):not(data):not(time):not(code):not(var):not(samp):not(kbd):not(sub):not(sup):not(i):not(b):not(u):not(mark):not(ruby):not(rb):not(rt):not(rtc):not(rp):not(bdi):not(bdo):not(span):not(br):not(wbr):not(ins):not(del):not(picture):not(img):not(iframe):not(embed):not(object):not(param):not(video):not(audio):not(source):not(track):not(map):not(area):not(math):not(svg):not(table):not(caption):not(colgroup):not(col):not(tbody):not(thead):not(tfoot):not(tr):not(td):not(th):not(form):not(label):not(input):not(button):not(select):not(datalist):not(optgroup):not(option):not(textarea):not(keygen):not(output):not(progress):not(meter):not(fieldset):not(legend):not(script):not(noscript):not(template):not(canvas)

Additionally, you will have to account for SVG and MathML namespaces.

  • One way would be to just add their tags in a similar manner.
  • In some cases (ad-blocking), it might be sufficient to prepend that selector with a few possible parents to avoid <svg> and <math> children. Something like :-webkit-any(body, div) > :not(.... See :is(), :matches(), :any().
  • Once implemented, Selectors Level 4 should allow something like :not(math *, svg *).
  • @namespace can be used, something like @namespace xhtml "http://www.w3.org/1999/xhtml"; xhtml|*:not(....

1 Comment

The specificity on this selector.....Each :not() is another 10 specificity points. The only way to beat that selector is with an ID.
2

If you just want to use custom tags instead of div:

:where(:not(:defined)) { 
    display: block; 
}

:not(:defined) selects the elements that are neither built in nor defined by you with customElements.define().

:where gives this rule low specificity, to avoid breaking grid, flow and display:inline.

This does not change the default inline display of actual custom elements that you pass to customElements.define(). I don't think it's a burden, as we already write specific code for such elements anyway.

3 Comments

The problem with this is that your custom elements ought to defined by your code if you're intending on using them and when they're defined this selector of course won't work for you.
Of course. As I stated from the start, it's not for actual custom elements, it's just for replacing div with custom tags.
This is exactly what I was looking for, thanks!!
1

You could do this using slightly modified code from this answer to get all registered custom tag names:

function getCustomElements() {
    const allElems = document.getElementsByTagName("*");
    let elementNames = [].map.call(allElems, el => el.nodeName.toLowerCase())
    elementNames = [...new Set(elementNames)];
    return elementNames.filter(name => customElements.get(name));
}

Which you can then use to style all custom elements:

const customElementSelector = getCustomElements().join();
document.querySelectorAll(customElementSelector).forEach(el => {
    el.style.border = "solid";
});

2 Comments

Where does customElements get defined? Is that a built-in property on window? I didn't see it in the answer you linked to, either.
Yes it is, I slightly modified the code of the other answer but the logic behind it is the same developer.mozilla.org/en-US/docs/Web/API/Window/customElements
1

Using javascript, this will return an array of custom elements

Array.from(document.querySelectorAll('*')).filter(el => el.tagName.includes('-'))

Comments

-3

You can simply use css like below:

custom-element{
    color: white;
    min-height: 20px;
}

I have tested this in Firefox and Chrome. Not sure about actual compatibility though. Please test on your environments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.