# Using text symbols in pseudo-elements accessibly

Generated content (the `::before` and `::after` pseudo-elements) is quite handy for styling elements without disrupting markup. We can use it for creating things like custom checkboxes without any extra elements.

%[https://codepen.io/MrRoboto/pen/OJxaGyb] 

Usually, we want to use an empty string as the value for the `content` property. This ensures that the pseudo-element is purely decorative and will not lead to unexpected announcements by assistive technologies.

```css
::before {
  content: "";
}
```

However, we might sometimes get the urge to use unicode characters in the content. A few common examples include:

* `*` at the end of labels for required inputs
    
* `#` or `🔗` near clickable headings (fragment links)
    
* `►` to indicate expandable content
    
* `❯` or `»` between breadcrumbs
    

If these symbols are used with `content`, it could cause a confusing experience for users who rely on assistive technologies.

```css
::before {
  /* ❌ don't do this! */
  content: "#";
}
```

In the future, we might be able to specify an empty alt text (Adrian Roselli has a [great article](https://adrianroselli.com/2020/10/alternative-text-for-css-generated-content.html) on this topic), but support is lacking currently.

```css
::before {
  /* someday */
  content: "#" / "";
}
```

## So what do we do?

Use svgs! The [mask technique](https://codepen.io/noahblon/post/coloring-svgs-in-css-background-images) that I demonstrated above in the custom checkbox demo is a great way to use svgs without leaving CSS.

```css
::before {
  --svg: url(...); /* can be a remote url or a data url */

  content: "";
  background-color: currentColor;
  -webkit-mask-image: var(--svg);
  mask-image: var(--svg);
}
```

## Okay but text is nice

Fine! I get it. Good news: I may have just found a way to do this accessibly. Let me show you.

We will still use the mask technique, but instead of using a real svg icon, we will construct one on the fly using a data url. And we will put our text inside the svg using a [`<text>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/text) element. For the purposes of this guide, let's use the `*` character to put at the end of a required label.

```xml
<svg xmlns="http://www.w3.org/2000/svg">
  <text>*</text>
</svg>
```

Let's add some attributes for positioning and styling the text. You can adjust these to your liking.

* 16x16 `viewBox` to correspond with default font size
    
* `font-family='system-ui'` so it adapts to the system font
    
* `font-size='1rem'` should be the default but you can adjust for your desired size
    
* `text-anchor='middle'` for horizontally centering the text
    
* `x='50%'` and `y='100%'`: I will admit I kept adjusting these randomly until the symbol was close to the center of the box 😅
    

```xml
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
  <text font-family="system-ui" font-size="1rem" text-anchor="middle" x="50%" y="100%">*</text>
</svg>
```

![A white asterisk symbol at the center of a box on a black background.](https://cdn.hashnode.com/res/hashnode/image/upload/v1673044759371/8ded204b-2e5d-4f20-8f25-9d45a8f95c0f.png align="center")

We can now put that in a data url and assign it to a custom property for ease of use. Note that some symbols might need to be [replaced](https://gist.github.com/jennyknuth/222825e315d45a738ed9d6e04c7a88d0) (for example, `#` becomes `%23`).

```css
--svg: url('data:image/svg+xml;utf8,<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><text font-family="system-ui" font-size="1rem" text-anchor="middle" x="50%" y="100%">*</text></svg>');
```

Sweet, now we can use it with the mask technique. We'll use the `::after` element because we want this to appear *after* the label text. We do need to give it a width and height explicitly (or use `position: absolute`). And let's also add [`forced-colors`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/forced-colors) support.

```css
label::after {
  content: "";
  -webkit-mask: var(--svg) no-repeat center;
  mask: var(--svg) no-repeat center;
  background-color: red;
  display: inline-block;
  width: 1em;
  height: 1em;

  @media (forced-colors: active) {
    background-color: CanvasText;
  }
}
```

And we're done!

%[https://codepen.io/MrRoboto/pen/XWBNGYL] 

Pretty neat, if you ask me. 😄
