tailwind-css

How to align input content and its label?


I'm trying to position <label> above a <textarea> in Tailwind CSS, but I'm running into an alignment issue. The problem is that the label text starts exactly where the border is, while the text inside the textarea starts slightly to the right due to padding.

I want to align the text inside input and the label vertically.

Here is the code

<div class="flex h-screen w-screen items-center justify-center">
  <div class="relative w-1/2">
    <textarea class="h-52 w-full rounded-md border-2 border-gray-500 py-2 outline-none focus:border-blue-400 px-3"></textarea>
    <label class="text-md absolute top-0 left-3 -mx-1 -translate-y-1/2 bg-white px-1">
      Comment
    </label>
  </div>
</div>

Here is the image


Solution

  • The <textarea> content is offset by 2px from the border. Hence, you can compensate this on the <textarea> by subtracting this border width from its padding:

    <script src="https://unpkg.com/@tailwindcss/browser@4.0.14"></script>
    
    <div class="flex h-screen w-screen items-center justify-center">
      <div class="relative w-1/2">
        <textarea class="h-52 w-full rounded-md border-2 border-gray-500 py-2 outline-none focus:border-blue-400 px-[calc(--spacing(3)-2px)]"></textarea>
        <label class="text-md absolute top-0 left-3 -mx-1 -translate-y-1/2 bg-white px-1">
          Comment
        </label>
      </div>
    </div>

    Or by adding 2px to the <label>:

    <script src="https://unpkg.com/@tailwindcss/browser@4.0.14"></script>
    
    <div class="flex h-screen w-screen items-center justify-center">
      <div class="relative w-1/2">
        <textarea class="h-52 w-full rounded-md border-2 border-gray-500 py-2 outline-none focus:border-blue-400 px-3"></textarea>
        <label class="text-md absolute top-0 left-[calc(--spacing(3)+2px)] -mx-1 -translate-y-1/2 bg-white px-1">
          Comment
        </label>
      </div>
    </div>

    You could also consider managing these spacing values in CSS variables. This makes the markup more verbose, but does mean there is a single source of truth whichever way you want to go, means you only need to change a value in one location and thus makes it more maintainable in the future:

    <script src="https://unpkg.com/@tailwindcss/browser@4.0.14"></script>
    
    <div class="flex h-screen w-screen items-center justify-center">
      <div class="relative w-1/2 [--px:--spacing(3)] [--border-width:2px]">
        <textarea class="h-52 w-full rounded-md border-(length:--border-width) border-gray-500 py-2 outline-none focus:border-blue-400 px-[calc(var(--px)-var(--border-width))]"></textarea>
        <label class="text-md absolute top-0 left-(--px) -mx-1 -translate-y-1/2 bg-white px-1">
          Comment
        </label>
      </div>
    </div>
    
    <div class="flex h-screen w-screen items-center justify-center">
      <div class="relative w-1/2 [--px:--spacing(3)] [--border-width:2px]">
        <textarea class="h-52 w-full rounded-md border-(length:--border-width) border-gray-500 py-2 outline-none focus:border-blue-400 px-(--px)"></textarea>
        <label class="text-md absolute top-0 left-[calc(var(--px)+var(--border-width))] -mx-1 -translate-y-1/2 bg-white px-1">
          Comment
        </label>
      </div>
    </div>