charnould
charnould

Reputation: 2929

Why a textarea is 1-line on desktop and 2-line on iOS (mobile)?

I'm working on a chatbot (as a newbie) and work on UI (using Tailwindcss).
For a reason I understand (different behaviors), I do not know how to handle it. Any clue? Thanks.

On desktop textarea is 1 row (perfect!)

enter image description here

But on mobile (iOS), it looks like this ("two" lines):

enter image description here

My code is:

<body>
    <footer
      class="fixed bottom-0 left-1/2 w-full max-w-4xl -translate-x-1/2 transform bg-white shadow-[0_0_40px_40px_rgba(255,255,255,1)]"
    >
      <div
        class="mx-6 mb-6 flex h-fit flex-none items-center justify-between gap-x-2 rounded-lg border border-gray-200 bg-white py-3 pr-2 pl-4 shadow-sm"
      >
        <textarea
          class="min-h-[24px] max-h-[240px] field-sizing-content flex-1 resize-none border-none text-base outline-0 placeholder:text-gray-400"
          id="prompt__input"
          type="text"
          name="message"
          placeholder="Comment puis-je vous aider ?"
        ></textarea>
        <button
          class="h-8 cursor-pointer px-3 text-xl font-black hover:rounded-lg hover:bg-gray-100 disabled:cursor-progress disabled:border-stone-200 disabled:text-stone-400"
          id="prompt__submit"
          type="button"
        >
          <svg
            class="fill-gray-600"
            aria-hidden="true"
            focusable="false"
            viewBox="0 0 16 16"
            width="22"
            height="22"
          >
            <path
              d="M.989 8 .064 2.68a1.342 1.342 0 0 1 1.85-1.462l13.402 5.744a1.13 1.13 0 0 1 0 2.076L1.913 14.782a1.343 1.343 0 0 1-1.85-1.463L.99 8Zm.603-5.288L2.38 7.25h4.87a.75.75 0 0 1 0 1.5H2.38l-.788 4.538L13.929 8Z"
            ></path>
          </svg>
        </button>
      </div>
    </footer>
</body>

Upvotes: 1

Views: 29

Answers (1)

rozsazoltan
rozsazoltan

Reputation: 9580

Limited availability for field-sizing

It is not available on either Firefox or Safari, so you need to look for an alternative solution.

field-sizing utilities are not available in v3

Note: The field-sizing utilities was introduced in TailwindCSS v4. If you still want to use it with v3, you'll need to create your own custom class. (See more: PR #14469)

.field-sizing-content {
  field-sizing: content;
}
.field-sizing-fixed {
  field-sizing: fixed;
}
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addUtilities }) {
      addUtilities({
        '.field-sizing-content' {
          'field-sizing': 'content';
        },
        '.field-sizing-fixed': {
          'field-sizing': 'fixed',
        },
      })
    })
  ]
}

Alternative: update height manually

Actually, I just inserted the original field-sizing solution and my new solution so that the results can be compared.

For the alternative solution, I set up a function on the textarea's input event that automatically adjusts the textarea's height to its scrollHeight, ensuring that the text will always be fully visible, with the max-h-[240px] acting as the constraint.

To ensure it works properly, the rows="1" setting is required to start with a single row by default, and an auto height setting is needed so that the scrollHeight actually starts decreasing when the content is deleted.

document.addEventListener("DOMContentLoaded", function () {
  const textarea = document.getElementById("prompt__input__alternative");
  
  // Update height to scrollHeight
  function updateHeight() {
    textarea.style.height = `auto`; /* for can reset height */
    textarea.style.height = `${textarea.scrollHeight}px`;
  }

  textarea.addEventListener("input", updateHeight);
  updateHeight();
});
<script src="https://unpkg.com/@tailwindcss/browser@4"></script>

<footer
  class="fixed bottom-0 left-1/2 w-full max-w-4xl -translate-x-1/2 transform bg-white shadow-[0_0_40px_40px_rgba(255,255,255,1)]"
>
  <p>Original with field-sizing-content</p>
  <div
    class="mx-6 mb-6 flex h-fit flex-none items-center justify-between gap-x-2 rounded-lg border border-gray-200 bg-white py-3 pr-2 pl-4 shadow-sm"
  >
    <textarea
      class="min-h-[24px] max-h-[240px] field-sizing-content flex-1 resize-none border-none text-base outline-0 placeholder:text-gray-400"
      id="prompt__input"
      type="text"
      name="message"
      placeholder="Comment puis-je vous aider ?"
    ></textarea>
    <button
      class="h-8 cursor-pointer px-3 text-xl font-black hover:rounded-lg hover:bg-gray-100 disabled:cursor-progress disabled:border-stone-200 disabled:text-stone-400"
      id="prompt__submit"
      type="button"
    >
      <svg
        class="fill-gray-600"
        aria-hidden="true"
        focusable="false"
        viewBox="0 0 16 16"
        width="22"
        height="22"
      >
        <path
          d="M.989 8 .064 2.68a1.342 1.342 0 0 1 1.85-1.462l13.402 5.744a1.13 1.13 0 0 1 0 2.076L1.913 14.782a1.343 1.343 0 0 1-1.85-1.463L.99 8Zm.603-5.288L2.38 7.25h4.87a.75.75 0 0 1 0 1.5H2.38l-.788 4.538L13.929 8Z"
        ></path>
      </svg>
    </button>
  </div>

  <p>Alternative with JavaScript</p>
  <div
    class="mx-6 mb-6 flex h-fit flex-none items-center justify-between gap-x-2 rounded-lg border border-gray-200 bg-white py-3 pr-2 pl-4 shadow-sm"
  >
    <textarea
      class="w-full min-h-[24px] max-h-[240px] h-auto resize-none border-none text-base outline-0 placeholder:text-gray-400"
      id="prompt__input__alternative"
      type="text"
      name="message"
      placeholder="Comment puis-je vous aider ?"
      rows="1"
    ></textarea>
    <button
      class="h-8 cursor-pointer px-3 text-xl font-black hover:rounded-lg hover:bg-gray-100 disabled:cursor-progress disabled:border-stone-200 disabled:text-stone-400"
      id="prompt__submit"
      type="button"
    >
      <svg
        class="fill-gray-600"
        aria-hidden="true"
        focusable="false"
        viewBox="0 0 16 16"
        width="22"
        height="22"
      >
        <path
          d="M.989 8 .064 2.68a1.342 1.342 0 0 1 1.85-1.462l13.402 5.744a1.13 1.13 0 0 1 0 2.076L1.913 14.782a1.343 1.343 0 0 1-1.85-1.463L.99 8Zm.603-5.288L2.38 7.25h4.87a.75.75 0 0 1 0 1.5H2.38l-.788 4.538L13.929 8Z"
        ></path>
      </svg>
    </button>
  </div>
</footer>

enter image description here enter image description here enter image description here

Alternative solution with contenteditable element

Actually, I just inserted the original field-sizing solution and my new solution so that the results can be compared.

The alternative solution works here even without JavaScript. The JavaScript is needed to hide and show the placeholder, and for that, I had to listen for the input event on the contenteditable div.

document.addEventListener("DOMContentLoaded", function () {
  const contentEditableDiv = document.getElementById("prompt__input__alternative");
  const placeholderSpan = document.getElementById("primpt__input__alternative__placeholder");

  // Hide placeholder when input length > 0
  function togglePlaceholder() {
    if (contentEditableDiv.textContent.trim().length > 0) {
      placeholderSpan.style.display = "none";
    } else {
      placeholderSpan.style.display = "inline";
    }
  }

  contentEditableDiv.addEventListener("input", togglePlaceholder);
  togglePlaceholder();
});
<script src="https://unpkg.com/@tailwindcss/browser@4"></script>

<footer
  class="fixed bottom-0 left-1/2 w-full max-w-4xl -translate-x-1/2 transform bg-white shadow-[0_0_40px_40px_rgba(255,255,255,1)]"
>
  <p>Original with field-sizing-content</p>
  <div
    class="mx-6 mb-6 flex h-fit flex-none items-center justify-between gap-x-2 rounded-lg border border-gray-200 bg-white py-3 pr-2 pl-4 shadow-sm"
  >
    <textarea
      class="min-h-[24px] max-h-[240px] field-sizing-content flex-1 resize-none border-none text-base outline-0 placeholder:text-gray-400"
      id="prompt__input"
      type="text"
      name="message"
      placeholder="Comment puis-je vous aider ?"
    ></textarea>
    <button
      class="h-8 cursor-pointer px-3 text-xl font-black hover:rounded-lg hover:bg-gray-100 disabled:cursor-progress disabled:border-stone-200 disabled:text-stone-400"
      id="prompt__submit"
      type="button"
    >
      <svg
        class="fill-gray-600"
        aria-hidden="true"
        focusable="false"
        viewBox="0 0 16 16"
        width="22"
        height="22"
      >
        <path
          d="M.989 8 .064 2.68a1.342 1.342 0 0 1 1.85-1.462l13.402 5.744a1.13 1.13 0 0 1 0 2.076L1.913 14.782a1.343 1.343 0 0 1-1.85-1.463L.99 8Zm.603-5.288L2.38 7.25h4.87a.75.75 0 0 1 0 1.5H2.38l-.788 4.538L13.929 8Z"
        ></path>
      </svg>
    </button>
  </div>

  <p>Alternative with contenteditable</p>
  <div
    class="mx-6 mb-6 flex h-fit flex-none items-center justify-between gap-x-2 rounded-lg border border-gray-200 bg-white py-3 pr-2 pl-4 shadow-sm"
  >
    <div class="relative w-full min-h-[24px] max-h-[240px] overflow-auto">
      <span id="primpt__input__alternative__placeholder" class="w-full text-gray-400 absolute top-0 left-0 z-0">
        Comment puis-je vous aider ?
      </span>
      <div
        contenteditable="true"
        class="relative z-10 w-full min-h-[24px] max-h-[240px] border-none text-base outline-0"
        id="prompt__input__alternative"
      ></div>
    </div>
    <button
      class="h-8 cursor-pointer px-3 text-xl font-black hover:rounded-lg hover:bg-gray-100 disabled:cursor-progress disabled:border-stone-200 disabled:text-stone-400"
      id="prompt__submit"
      type="button"
    >
      <svg
        class="fill-gray-600"
        aria-hidden="true"
        focusable="false"
        viewBox="0 0 16 16"
        width="22"
        height="22"
      >
        <path
          d="M.989 8 .064 2.68a1.342 1.342 0 0 1 1.85-1.462l13.402 5.744a1.13 1.13 0 0 1 0 2.076L1.913 14.782a1.343 1.343 0 0 1-1.85-1.463L.99 8Zm.603-5.288L2.38 7.25h4.87a.75.75 0 0 1 0 1.5H2.38l-.788 4.538L13.929 8Z"
        ></path>
      </svg>
    </button>
  </div>
</footer>

Upvotes: 1

Related Questions