Search code examples
csstailwind-css

Why does `placeholder-shown:no-underline` work but `placeholder:no-underline` doesn't?


I expected placeholder:no-underline to remove the underline of an input's placeholder. However, placeholder-shown:no-underline does work. But I don't understand the CSS that is being created. Why does one work and the other not?

Example: https://play.tailwindcss.com/gZIVyRDi6y


Solution

  • TL;DR

    Text-decoration on placeholder (placeholder:no-underline) doesn't work with text-decorated input (underline) in Chrome and Edge possibly due to a bug in Blink. You can see both ways work fine in Firefox. You can stick with placeholder-shown:no-underline for the same result in this case.


    First you need to know ::placeholder and :placeholder-shown target different things. Here ::placeholder targets the placeholder text in the input, while :placeholder-shown targets the input itself when it's currently displaying placeholder.

    The behavior of adding underline on the input element and on the placeholder text is different as well. When underline is added on the input, all input texts will be underlined (along with the placeholder text by default[1]), otherwise only the placeholder text will be underlined.

    In your case, underline is added on the input (which effects the placeholder as stated above), while placeholder-shown:no-underline removes this underline only when the placeholder text is shown (no input), effectively removes the underline for ::placeholder only. Hence, doing so is fine.

    On the other hand, using ::placeholder should be working, as you are styling the placeholder text directly. However, in Chrome and Edge, when there are visible text-decoration set on the input element itself, setting text-decoration on the placeholder has no effect no matter what. (Even using vendor prefix. In fact, you can see in the UA shadow DOM that the text-decoration is correctly applied, just not having any effect.) This looks like a bug to me unless I'm missing something.

    Below example behaves differently in Chrome and FireFox:

    <script src="https://cdn.tailwindcss.com"></script>
    
    <input class="underline placeholder-shown:no-underline" placeholder="Works for all browser" />
    <input class="underline placeholder:no-underline" placeholder="Works only in Firefox" />


    [1] As per spec the placeholder text is a tree-abiding pseudo-element, so it inherits any inheritable properties from their originating element including the text-decoration styles.