sodcalculator

10 Tech How-To

CSS-Only Custom Elements: Styling Defaults & Browser Behavior

Guide 10-19834 · Updated · Step by step

This guide explains how to style custom elements using only CSS, covering the default styling behavior, the display property, and how browsers handle unknown elements. You’ll learn to make your custom tags look and behave like standard HTML elements, without JavaScript.

What You’ll Need

  • A basic understanding of HTML and CSS (selectors, properties, values).
  • A text editor and a web browser (any modern browser like Chrome, Firefox, Safari, or Edge).
  • No JavaScript required – this is purely CSS.

Step-by-Step

  1. Create a custom element in HTML. Use a tag name with a hyphen, e.g., <my-widget>. This is required by the HTML spec to avoid conflicts with future built-in elements. Example: <my-widget>Hello</my-widget>.
  2. Open your CSS file or style block. Write a rule targeting your custom element. For example: my-widget { display: block; }.
  3. Set the default display value. By default, unknown elements are rendered as inline. This is the most important step. Decide what display role your element should have: block, inline, inline-block, flex, grid, etc. Set it explicitly.
  4. Style it like any other element. Once the display is set, you can apply any CSS properties: margins, padding, colors, fonts, borders, background, etc. For example: my-widget { display: block; padding: 10px; border: 1px solid #ccc; }.
  5. Style child elements. Use descendant selectors to style elements inside your custom element. For example: my-widget span { font-weight: bold; }.
  6. Use attribute selectors for state. You can style based on attributes, like my-widget[hidden] { display: none; } or my-widget[disabled] { opacity: 0.5; }.
  7. Test in different browsers. All modern browsers treat unknown elements the same way, but older browsers (IE 9 and below) may not allow styling of unknown elements unless you create them via JavaScript. For current browsers, this is not an issue.
  8. Consider using the :defined pseudo-class. When you use custom elements with JavaScript (custom elements v1), the :defined selector matches elements that have been defined. For pure CSS, this is not needed, but it’s good to know.

Common Mistakes

  • Forgetting to set display. If you don’t set a display value, your custom element will be inline, which often breaks layout expectations (e.g., margins and padding won’t work as expected on inline elements).
  • Using a tag name without a hyphen. Custom elements must have a hyphen (e.g., <my-element>). Using a single word like <mytag> is not valid and may be treated as an unknown built-in element.
  • Assuming default block behavior. Many people assume unknown elements are block-level; they are not. Always set display explicitly.
  • Not resetting inherited properties. Custom elements inherit properties from their parent, like color and font. If you want a clean slate, reset them (e.g., all: initial).
  • Using IDs or inline styles excessively. That’s not specific to custom elements, but it’s a common mistake when trying to force styling.

Tips

  • Use a class or attribute for variants. For example, <my-widget type="primary"> and style my-widget[type="primary"] { ... }.
  • Combine with CSS variables. Define custom properties on the custom element to make it themeable. Example: my-widget { --main-color: #333; color: var(--main-color); }.
  • Use the :host selector in shadow DOM. If you’re using shadow DOM (with JavaScript), :host styles the custom element itself from inside the shadow root. This is more advanced but powerful.
  • Keep it semantic. Use custom elements for meaningful structure, not just for styling hooks. Use them to represent a component or a distinct piece of content.
  • Test with a reset stylesheet. Different browsers have different default styles. A reset (like a simple * { margin: 0; padding: 0; box-sizing: border-box; }) helps ensure consistency.

Troubleshooting

  • My custom element has no styling. Check the tag name – it must match exactly (case-sensitive in HTML). Also, ensure your CSS rule is not overridden by a more specific selector. Use the browser’s dev tools to inspect the element and see if the rule is applied.
  • My element is inline and I want it block. Set display: block (or any other value) explicitly. If you want it to behave like a div, use display: block.
  • Margins/padding don’t work. This is almost always because the element is inline. Set display: inline-block or block.
  • The element is not showing at all. Check if you have a display: none rule. Also, ensure the element is not inside a container with overflow: hidden or zero height. Use dev tools to see if the element is rendered.
  • It works in one browser but not another. All modern browsers support styling unknown elements. If you’re testing in an old browser (IE9 and below), you need to create the element via JavaScript (e.g., document.createElement('my-widget')) to enable styling. For current browsers, this is not an issue.
  • My custom element is not accessible. Custom elements are not automatically accessible. You need to add ARIA roles and labels as needed. For example, if it’s a button, add role="button" and tabindex="0".

Frequently Asked Questions

Can I style custom elements without JavaScript?

Yes, absolutely. You can style custom elements with pure CSS. The browser treats them as unknown elements and applies your CSS rules. The only limitation is that you cannot define their behavior (like click handlers) without JavaScript, but styling is fully possible.

What is the default display value of a custom element?

By default, unknown elements are rendered as inline. This means they behave like a span. You should always set a display value to get the layout you want.

Do custom elements need a hyphen?

Yes, the HTML spec requires custom element names to contain a hyphen. This is to ensure they don’t conflict with future built-in elements. For example, <my-element> is valid, but <myelement> is not.

Can I use custom elements with CSS frameworks like Bootstrap?

Yes, you can. CSS frameworks typically style based on classes and element selectors. You can add classes to your custom elements and use the framework’s utilities. However, the framework’s base styles for unknown elements won’t apply unless you write your own.

How do I make a custom element behave like a button?

To make a custom element behave like a button, you need to set display: inline-block (or block), add cursor: pointer, and handle click events with JavaScript. For accessibility, add role="button" and tabindex="0".

Is there any performance impact of using many custom elements?

Using many custom elements with CSS only has no significant performance impact. The browser parses them like any other element. If you use shadow DOM or custom elements v1 (with JavaScript), there may be a slight overhead, but for pure CSS, it’s negligible.

Related

General steps for current mainstream versions; menus can differ by device and version. See the disclaimer or report an error.

More in this bed

The whole Tech How-To bed →