<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: hannah 🐙</title>
    <description>The latest articles on DEV Community by hannah 🐙 (@erhannah).</description>
    <link>https://dev.to/erhannah</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F64159%2F73e08790-9d23-4f61-9a01-6cdae49a7b5c.jpeg</url>
      <title>DEV Community: hannah 🐙</title>
      <link>https://dev.to/erhannah</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/erhannah"/>
    <language>en</language>
    <item>
      <title>Introducing Gradio 5.0 🪄 Build and share AI web apps in minutes</title>
      <dc:creator>hannah 🐙</dc:creator>
      <pubDate>Wed, 16 Oct 2024 00:34:09 +0000</pubDate>
      <link>https://dev.to/erhannah/introducing-gradio-50-build-and-share-ai-web-apps-in-minutes-21bk</link>
      <guid>https://dev.to/erhannah/introducing-gradio-50-build-and-share-ai-web-apps-in-minutes-21bk</guid>
      <description>&lt;p&gt;Hey folks 👋 Today we're launching Gradio 5.0 on &lt;a href="https://www.producthunt.com/posts/gradio-5-0" rel="noopener noreferrer"&gt;Product Hunt&lt;/a&gt;. If you've never heard of Gradio, let's fix that!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Gradio?
&lt;/h2&gt;

&lt;p&gt;Gradio is an open-source library that allows you to create customizable web interfaces for your machine learning models with Python. Whether you have your own model, or you want to try out a cool new open-source LLM without any hassle, Gradio is the answer. It's designed to be intuitive for developers (both newbies and experienced) and accessible for users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Start Tutorial
&lt;/h2&gt;

&lt;p&gt;Here's a super simple demonstration of how you can create and deploy a demo via Hugging Face Spaces with a Gradio Chatbot template and customize it to our liking.&lt;/p&gt;

&lt;p&gt;Create a Space for your Gradio demo &lt;a href="https://huggingface.co/new-space?sdk=gradio" rel="noopener noreferrer"&gt;here&lt;/a&gt;, and select the Chatbot template. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExeTN5cDl1NnJzMWpwYzdpOGxjY3JrMHY0OXBta2p1cHdkMmZxMHo5eiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/znkPrbc0kCVoIX0InR/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExeTN5cDl1NnJzMWpwYzdpOGxjY3JrMHY0OXBta2p1cHdkMmZxMHo5eiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/znkPrbc0kCVoIX0InR/giphy.gif" width="480" height="296"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you'd rather just run a Gradio demo locally, you can skip the next couple of steps, run &lt;code&gt;pip install gradio&lt;/code&gt; and copy and paste the script further down. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You'll see your Gradio demo building at first, and then voila! You should be able to try out your own chatbot. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhn9zrekzz7nz88rmwwf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhn9zrekzz7nz88rmwwf.png" alt="basic chatbot conversation" width="800" height="568"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What if we want to customise this a little bit?&lt;/p&gt;

&lt;p&gt;Let's change "friendly chatbot" to "pirate chatbot". I also want to test out the &lt;a href="//mistralai/Mistral-7B-Instruct-v0.3"&gt;Mistral 7B Instruct&lt;/a&gt; LLM instead. You can either edit the &lt;code&gt;app.py&lt;/code&gt; file in your Space repo, or you can clone the repo and run it locally with the command &lt;code&gt;gradio app.py&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Here's my script with the changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import gradio as gr
from huggingface_hub import InferenceClient

client = InferenceClient("mistralai/Mistral-7B-Instruct-v0.3")


def respond(
    message,
    history: list[tuple[str, str]],
    system_message,
    max_tokens,
    temperature,
    top_p,
):
    messages = [{"role": "system", "content": system_message}]

    for val in history:
        if val[0]:
            messages.append({"role": "user", "content": val[0]})
        if val[1]:
            messages.append({"role": "assistant", "content": val[1]})

    messages.append({"role": "user", "content": message})

    response = ""

    for message in client.chat_completion(
        messages,
        max_tokens=max_tokens,
        stream=True,
        temperature=temperature,
        top_p=top_p,
    ):
        token = message.choices[0].delta.content

        response += token
        yield response


demo = gr.ChatInterface(
    respond,
    additional_inputs=[
        gr.Textbox(value="You are a pirate Chatbot.", label="System message"),
        gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
        gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
        gr.Slider(
            minimum=0.1,
            maximum=1.0,
            value=0.95,
            step=0.05,
            label="Top-p (nucleus sampling)",
        ),
    ],
)


if __name__ == "__main__":
    demo.launch()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're running this locally, simply run &lt;code&gt;gradio app.py&lt;/code&gt; (or whatever you named this script file). If you edited this via the Hugging Face Spaces platform, you should just see it building and running in Spaces pretty quickly!&lt;/p&gt;

&lt;p&gt;Now let's give it a go. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExZnNzanp3ZWJkdnkzeHZubWlxYmUwazc2NnpsdTB6ZmZ5OTV4bjByZyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/Lcd8DqekGW9LmRYAeA/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExZnNzanp3ZWJkdnkzeHZubWlxYmUwazc2NnpsdTB6ZmZ5OTV4bjByZyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/Lcd8DqekGW9LmRYAeA/giphy.gif" width="480" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it! How cool is that? Plus, users of your space can also simply edit that &lt;code&gt;pirate&lt;/code&gt; text with anything they want as well via the Additional Inputs section in the UI. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw0h2u2ipr96syibdc5qg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw0h2u2ipr96syibdc5qg.png" alt="Image description" width="800" height="194"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can embed this Space anywhere, or you can share it via a &lt;a href="https://www.gradio.app/guides/sharing-your-app#sharing-demos" rel="noopener noreferrer"&gt;Share link&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  So what's new in Gradio 5.0?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Server Side Rendering&lt;/strong&gt;: Massive performance improvements &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI Components&lt;/strong&gt;: We've updated our UI components and given them a sleeker look&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Major security enhancements&lt;/strong&gt;: Safely deploy your web app without worrying about web security&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;...and a lot more. &lt;/p&gt;

&lt;p&gt;Give it a try and see how quickly you can turn your ideas into shareable web apps! If you're stuck on how to start, have a play around with our &lt;a href="https://www.gradio.app/playground" rel="noopener noreferrer"&gt;Gradio Playground&lt;/a&gt; and have our LLM build a Gradio app for you.&lt;/p&gt;

&lt;p&gt;Don't forget to check out Gradio 5.0 on &lt;a href="https://www.producthunt.com/posts/gradio-5-0" rel="noopener noreferrer"&gt;Product Hunt&lt;/a&gt; and if you have a moment, we'd love for your support if you find it useful. &lt;/p&gt;

&lt;p&gt;Happy coding! 🚀&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>webdev</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>13 ways to level up your site's accessibility ✨</title>
      <dc:creator>hannah 🐙</dc:creator>
      <pubDate>Thu, 23 Jul 2020 12:49:57 +0000</pubDate>
      <link>https://dev.to/erhannah/13-ways-to-level-up-your-site-s-accessibility-22c6</link>
      <guid>https://dev.to/erhannah/13-ways-to-level-up-your-site-s-accessibility-22c6</guid>
      <description>&lt;p&gt;I recently posted a &lt;a href="https://twitter.com/erhannah/status/1284884344918675456?s=20" rel="noopener noreferrer"&gt;thread on twitter&lt;/a&gt; on making your site more accessible. It turned out to be super helpful for a lot of people, so I wanted to condense this into a post for people to refer to. &lt;/p&gt;

&lt;p&gt;Having researched a little more into the topic for a new client, I found some changes I could make to my projects which could make all the difference to someone's experience when navigating a site using assistive technology. &lt;/p&gt;




&lt;h3&gt;
  
  
  1. Planning Ahead
&lt;/h3&gt;

&lt;p&gt;Something that I need to work on is thinking about accessibility from the beginning. I’m working on it, but i still have a couple projects where I’m retroactively fixing my a11y blunders, including my own new site. I’m calling myself out here. It’s poor etiquette and wastes time.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Uppercase Text Properly
&lt;/h3&gt;

&lt;p&gt;Instead of typing out uppercase content in all caps manually, use &lt;code&gt;text-transform: uppercase&lt;/code&gt; on its class or id in CSS instead. this is because some screen readers read capitalised text letter by letter. Can you imagine how annoying that would be?!&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Use Aria-label
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;alt&lt;/code&gt; tag is used for describing images, but have you used the &lt;code&gt;aria-label&lt;/code&gt; attribute? This is used to describe an elements role for screen readers. e.g. On a button that says “close” the &lt;code&gt;aria-label&lt;/code&gt; could be “back to homepage” to give better context. You can read more &lt;a href="https://a11y-101.com/development/aria-label" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Specify the Main Content
&lt;/h3&gt;

&lt;p&gt;Be sure to use one &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt; tag to specify where the main content is. This helps less abled users to ignore any fancy fluff on your site and go straight to where the main content is.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Hide Elements Properly
&lt;/h3&gt;

&lt;p&gt;When hiding absolutely positioned content using left: -9999px instead of using display: none, it’s not visible on a typical screen but this text is still technically visible for a screen reader, so it will still read whatever it is.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Use &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; when its a button
&lt;/h3&gt;

&lt;p&gt;Gosh darn it fellow devs, let’s stop using &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s as buttons. I know they’re by default really ugly and need style stripping, but you’re losing all the button functionality such as keyboard events which screen readers look for to help with navigation.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Style Links Sensibly
&lt;/h3&gt;

&lt;p&gt;When adding a link, you may be tempted to use &lt;code&gt;text decoration: none&lt;/code&gt; and change the colour on hover. Don’t do this! people who are colourblind struggle with seeing it as a link and won’t see that change. plus, why not be more creative than that?! Here‘s a snazzier example &lt;a href="https://freefrontend.com/css-link-styles/" rel="noopener noreferrer"&gt;(credit)&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ffreefrontend.com%2Fassets%2Fimg%2Fcss-link-styles%2Funderline-hover-test.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ffreefrontend.com%2Fassets%2Fimg%2Fcss-link-styles%2Funderline-hover-test.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Size Text Properly
&lt;/h3&gt;

&lt;p&gt;Text sizing is a biggie for people with visual needs. Don’t make your text so small! A good point of reference - body text should be minimum 16px, small text summaries minimum 12px. It’s generally better to use relative screen sizing though. Read more &lt;a href="https://css-tricks.com/accessible-font-sizing-explained/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Don't Remove that Outline!
&lt;/h3&gt;

&lt;p&gt;Using &lt;code&gt;outline: none&lt;/code&gt; (commonly done on text inputs) is keyboard user unfriendly. They use the outline to see which element they’re focused on when they’re navigating through a page, so won’t know what they’re currently interacting with. to remove it sensibly, try using &lt;a href="https://github.com/nuclei/unfocus" rel="noopener noreferrer"&gt;unfocus&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  10. Check your Site
&lt;/h3&gt;

&lt;p&gt;There are some great resources which allow you to check your site with a checklist. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A resource for further info and a checklist: &lt;a href="http://a11yproject.com" rel="noopener noreferrer"&gt;A11yproject&lt;/a&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A similar site: &lt;a href="http://a11y.me" rel="noopener noreferrer"&gt;A11y.me&lt;/a&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A repo of a11y css stylesheets for your project: &lt;a href="http://github.com/mike-engel/a11y-css-reset" rel="noopener noreferrer"&gt;a11&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  11. Audit your Site
&lt;/h3&gt;

&lt;p&gt;Google Chrome has an open source toolkit for site accessibility auditing that you should check out. You can install this in your own project for testing. See &lt;a href="https://github.com/GoogleChrome/accessibility-developer-tools" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  12. Double Check!
&lt;/h3&gt;

&lt;p&gt;Khan Academy has an open sourced accessibility visualisation toolkit, tota11y, so you can see how your site performs with assistive tech. How awesome is that?! Check it out &lt;a href="http://github.com/Khan/tota11y" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  13. See for Yourself
&lt;/h3&gt;

&lt;p&gt;If you have time, try using a screen reader yourself. On a Mac, turn on VoiceOver using Cmd + 5. Navigate through your site using tab and H/B/T/L to get to the next heading, button, table and list. The closed captions will read out the aria labels! Credit &lt;a href="https://stackoverflow.com/questions/56427619/how-to-test-your-aria-tags-on-your-website/56510982#56510982" rel="noopener noreferrer"&gt;to this StackOverflow answer&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;There’s loads more on the internet to learn from and I’m just scratching the surface. I’m trying be a decent citizen of the internet and hope I can encourage other devs to do so too. Feel free to share more valuable tips!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cover image credit to &lt;a href="http://mds.is/a11y" rel="noopener noreferrer"&gt;mds&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Hi! I'm Hannah. I'm a virtual reality developer, senior frontend developer, vrcalm cofounder helping dementia patients, and tech for good enthusiast. 🌎&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>webdev</category>
      <category>html</category>
      <category>css</category>
    </item>
    <item>
      <title>Adding pseudo-elements on input elements 🚫</title>
      <dc:creator>hannah 🐙</dc:creator>
      <pubDate>Mon, 11 May 2020 14:40:21 +0000</pubDate>
      <link>https://dev.to/erhannah/adding-pseudoelements-on-input-elements-5bdk</link>
      <guid>https://dev.to/erhannah/adding-pseudoelements-on-input-elements-5bdk</guid>
      <description>&lt;p&gt;Before you sink hours into trying to work out why that &lt;code&gt;::after&lt;/code&gt; pseudo-element isn't working on your text input, let me save you some time and tell you that you can't - without some extra work that is. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;TLDR; Add the &lt;code&gt;::after&lt;/code&gt; to a sibling &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; element.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The reason being is that pseudo-elements are only supported on container elements. &lt;/p&gt;

&lt;p&gt;W3C's specification states the following: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Authors specify the style and location of generated content with the :before and :after pseudo-elements. As their names indicate, the :before and :after pseudo-elements specify the location of content before and after an element's document tree content. The 'content' property, in conjunction with these pseudo-elements, specifies what is inserted.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;But what does that mean!?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pseudo-elements are rendered in your code as child elements of parent elements.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This means that rendering an &lt;code&gt;::after&lt;/code&gt; selector on a button is fine, because it can be rendered as a child within a &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; component without a problem because it's a container element, as shown below. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4ik4eek095xz662y4bjv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4ik4eek095xz662y4bjv.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, the below code won't work, because &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; elements don't support children. It's not a container element, like &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; is. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F88ffxohwlu0xnsgoygqz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F88ffxohwlu0xnsgoygqz.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're not well acquainted with &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; elements, here's an example of &lt;em&gt;valid&lt;/em&gt; usage of an &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; element. Observe the fact that there's an immediate closing tag without any children within that element. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fngih6ag5aopki95bfz95.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fngih6ag5aopki95bfz95.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See the problem? An &lt;code&gt;::after&lt;/code&gt; pseudo-element can't render within an &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; because it's not a container element; it cannot support any children. So how do we get around this? &lt;/p&gt;

&lt;p&gt;The solution is to apply an &lt;code&gt;::after&lt;/code&gt; pseudo-element on a sibling &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; element. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fl4km5ufp4f6tqwssxuwe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fl4km5ufp4f6tqwssxuwe.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, we are adding an &lt;code&gt;::after&lt;/code&gt; selector when the &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; focus state is active. By targeting the focus state, we can append a pseudo-element to an empty adjacent &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; element and work around the &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;'s container issue. &lt;/p&gt;

&lt;p&gt;Here's a codepen to demonstrate this. &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/hannahblair/embed/KKdePgm?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I hope you found this useful! Follow me on the bird app &lt;a href="http://www.twitter.com/erhannah" rel="noopener noreferrer"&gt;@erhannah&lt;/a&gt; for more web dev shenanigans/virtual reality chat/dog pics. ✨ &lt;/p&gt;

&lt;p&gt;N.B: Yes, I know you could also get around this with jQuery. But it's 2020. &lt;/p&gt;




&lt;p&gt;&lt;em&gt;Hi! I'm Hannah. I'm a virtual reality developer, senior frontend developer, vrcalm cofounder helping dementia patients, and tech for good enthusiast.&lt;/em&gt; 🌎&lt;/p&gt;

</description>
      <category>css</category>
      <category>javascript</category>
      <category>html</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
