---
title: "Using WebC for progressively-enhanced UI elements"
date: 2023-02-23T10:17:01
slug: using-webc-for-progressively-enhanced-ui-elements
---
Now I'm back in Eleventy-land, I thought I'd give [WebC](https://github.com/11ty/webc) a go. For those unaware, it's a templating language that generates Web Components, complete with asset bundling.
But unlike regular Web Components, you can build things that aren't completely reliant on Javascript. Because WebC is server-side rendered initially, you can provide fallback elements that will still render if Javascript fails or is disabled.
To try it out, I created a simple live Markdown editor. It's simply a text area that lets you input Markdown, and then live-renders it to the side. I've got a new 11ty project, where every file is using `webc` extensions, and global components are configured. I've created a new file, `_components/rich-textarea.webc`.
To start with, I'll add my markup, which is just a textarea and a div for showing the output.
```html
```
By giving the `webc:root` attribute to the `template`, when it renders WebC will just strip out the tags and leave me with the textarea and div inside my Web Component tag.
Now in my `index.webc` I can use it:
```html
```
And that renders, albeit a bit un-inspiring:

## Styling
Next, up, I want to add some styles to my component. I can include these directly in my `webc` file and they'll be bundled at build time:
```html
```
The interesting parts are the `:host` and the `:defined` pseudoclasses. `:host` refers to the webcomponent itself, I've cheated a bit and used it to give some flex styling to help make things fullscreen, but I'm not sure if that's best practice or not.
The `:defined` pseudoclass tells us if the Web Component has been defined or not - with Javascript disabled, this will always be false and so we want to hide the render area when that's the case. It's also false right now because we haven't added any javascript.
So, with this CSS, we now get a full-width textarea:

## Adding interactivity
This is the final bit! Now, all we need is a bit of Javascript to make things interactive. We can add a `script` tag to our component, and in that tag use `window.customElements.define` to define our Web Component:
```html
```
So, when the Javascript has loaded and `connectedCallback` runs, we're getting the content we've passed as a prop, and using the [MarkdownIt](https://github.com/markdown-it/markdown-it) library to transform it to HTML and render it within our `rich-text-root`.
Then, whenever the user triggers a `change` or `keyup` event on the textarea, we update that content again, giving us a live reload.
The nice part about this is that because we're using WebC, the markup it generates already includes a fallback:
```html
```
That means that, if Javascript is enabled then I get the full live-edit functionality:

And when we disable Javascript, we just get the textarea on it's own as a fallback:
