newline char \n for – Tal E Feb 04 '20 at 15:25

  • If this is a limitation of Safari, maybe one idea is to create a transparent div that sits on top of the textArea, and shows if the content is empty, and hides if not.. – Keith Feb 04 '20 at 15:32
  • 4 Answers4

    2

    This is maybe a Safari limitation, so one idea is to emulate the placeholder.

    All we need to do is place transparent div over the top of the textarea, and then make this visible / invisible based on the value.

    Also disable mouse select & pointer events to prevent the div capturing, these are just simple css pointer-events & user-select css properties..

    Below is an example.

    const ta = document.querySelector('textarea');
    const pp = document.querySelector('.placeholder');
    console.log(ta);
    ta.addEventListener('input', () => {
      pp.classList.toggle('hidden', ta.value !== '');
    });
    .holder {
      position: relative;
      overflow: hidden;
    }
    .placeholder {
      pointer-events: none;
      user-select: none;
      position: absolute;
      color: silver;
      padding: 0.2rem 0.2rem;
    }
    .hidden {
      display: none;
    }
    textarea {
      width: 200px;
    }
    <div class="holder">
      <div class="placeholder">
        This is the place holder<br>
        Multiline<br>
        Ok?
      </div>
      <textarea required="true" rows="5"></textarea>
    </div>
    Keith
    • 22,005
    • 2
    • 27
    • 44
    2

    Line breaks (\n) in a textarea field work as expected in Chrome. However, the Safari default stylesheet overrides these line breaks.

    We can mock a placeholder by adding a background image to the text area.

    If there is no text in the textarea, show the background image. If the textarea is in focus, or there is a value, don't show the background image.

    <TextField
      onChange={onTexfieldChange}
      value={textAreaValue}
      id={'text-area-img-placeholder'}
      style={{backgroundImage: (textAreaValue) && 'none'}}
    />
    

    I am using styled components in React, but you can replace TextField with HTML textarea.

    The style attribute of the TextField ensures that if there is a value in the textarea (textAreaValue), the background image is removed.

    #text-area-img-placeholder {
        background-image: url(./fileName.png);
        background-repeat: no-repeat;
        background-size: contain;
    }
    
    #text-area-img-placeholder:focus{
     background-image: none;
    }
    

    Add this CSS to cover the background image over the entire textarea. When the HTML is in focus, remove the background image.

    • I cannot believe that only Safari cannot display linebreaks inside textarea placeholders and such hacks are necessary. For multilingual sites you need to create such "background images" for each language. I hope the Safari developers fix this ASAP. Today is 2023-01-16. – Avatar Jan 16 '23 at 15:41
    1
    1. &#x0a; is used to break the line in placeholder.
    2. For safari add additional script to handle multiple line placeholder. jQuery is required for below script.

    $(function() {
      var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
      
      // Disable for chrome which already supports multiline
      if (! (!!window.chrome && !isOpera)) {
        var style = $('<style>textarea[data-placeholder].active { color: #ccc; }</style>')
        $('html > head').append(style);
        
        $('textarea[placeholder]').each(function(index) {
          var text  = $(this).attr('placeholder');
          var match = /\r|\n/.exec(text);
          
          if (! match)
            return;
          
          $(this).attr('placeholder', '');
          $(this).attr('data-placeholder', text);
          $(this).addClass('active');
          $(this).val(text);
        });
        
        $('textarea[data-placeholder]').on('focus', function() {
          if ($(this).attr('data-placeholder') === $(this).val()) {
            $(this).attr('data-placeholder', $(this).val());
            $(this).val('');
            $(this).removeClass('active');
          }
        });
        
        $('textarea[data-placeholder]').on('blur', function() {
          if ($(this).val() === '') {
            var text = $(this).attr('data-placeholder');
            $(this).val(text);
            $(this).addClass('active');
          }
        });
      }
    });
    <html>
      <head>
        <script src="https://code.jquery.com/jquery-2.2.4.js" integrity="sha256-iT6Q9iMJYuQiMWNd9lDyBUStIq/8PuOW33aOqmvFpqI=" crossorigin="anonymous"></script>
      </head>
    <body>
       <textarea rows="5" placeholder="first line &#x0a;second line &#x0a;third line"></textarea>
      </body>
    </html>
    0

    Here one way how to set the linebreaks directly inside the string. However, it does not work in Safari either.

    HTML:

    <textarea></textarea>


    Javascript/Jquery:

    var placeholder_text = `• First line
    • Second line
    • Third line`;
    
    $(document).ready(function()
    {
        $('textarea').attr('placeholder', placeholder_text)
    });
    

    JSFiddle: https://jsfiddle.net/gt1ry6d0/2/

    Avatar
    • 14,622
    • 9
    • 119
    • 198