When are <br> elements ignored when within a paragraph?

Viewed 4329

I have found out that sometimes, <br> elements are not rendered in the browsers I use (Firefox and Chrome).

<p>Hello<br></p>
<p>Hello<br></p>

will be rendered the same as :

<p>Hello</p>
<p>Hello</p>

In the same way,

<p>Hello <a href="https://ddg.gg">ddg<br></a></p>
<p>Hello</p>

and :

<p>Hello <a href="https://ddg.gg">ddg</a></p>
<p>Hello</p>

will also be rendered without any linebreaks when opened in the browser.

I couldn't find the section in the HTML spec that specifies this behavior, do you know where to find the spec for this or could you phrase this behavior in a simple way ?

I would also be interested in reasons for having this behavior if you know them.

EDIT : I know it is quite "incorrect" to place br elements at this position in the HTML, I'm not the one who generates this HTML, but I need to convert this HTML to another format so I'm interested in understanding how browsers handle this case.

8 Answers

In my opinion most browsers follow the WHATWG specification and I would do it also. World Wide Web Consortium (W3C) has On 28 May 2019 announced that WHATWG would be the sole publisher of the HTML and DOM standards. If we have in this specification following rules only, then I would follow those rules.

WHATWG has following recommendations for br element:

The br element represents a line break.

Note: While line breaks are usually represented in visual media by physically moving subsequent text to a new line, a style sheet or user agent would be equally justified in causing line breaks to be rendered in a different manner, for instance as green dots, or as extra spacing.

br elements must be used only for line breaks that are actually part of the content, as in poems or addresses.

The following example is correct usage of the br element:

<p>P. Sherman<br>
42 Wallaby Way<br>
Sydney</p>

br elements must not be used for separating thematic groups in a paragraph.

The following examples are non-conforming, as they abuse the br element:

<p><a ...>34 comments.</a><br>
<a ...>Add a comment.</a></p>
<p><label>Name: <input name="name"></label><br>
<label>Address: <input name="address"></label></p>

Here are alternatives to the above, which are correct:

<p><a ...>34 comments.</a></p>
<p><a ...>Add a comment.</a></p>
<p><label>Name: <input name="name"></label></p>
<p><label>Address: <input name="address"></label></p>

If a paragraph consists of nothing but a single br element, it represents a placeholder blank line (e.g. as in a template). Such blank lines must not be used for presentation purposes.

Any content inside br elements must not be considered part of the surrounding text.

Note: This element has rendering requirements involving the bidirectional algorithm.

Source: WHATWG: The br element

In your examples you have br elements in <br></p> and in <br></a></p> on the end of <p> element. The new line on the end of this element does nothing, but only in this case. In such of this cases you can ignore it. It is also the same in the case of br elements in <br></a></div> and in <br></div> on the end of <div> element.

Cite from WHATWG recommendations (see above): If a paragraph consists of nothing but a single br element, it represents a placeholder blank line. Also it is not empty (like user kalkronline wrote). And in case of W3C and WHATWG opinions conflict user agents have to follow WHATWG recomandations (see above).

Do not forget about style possibility (for ex. clear) for br element.


Update from 25/06/2020

I want to post and explain the cite from WHATWG recommendations again(see above):

If a paragraph consists of nothing but a single br element, it represents a placeholder blank line.

This is showed like:

p{border:1px dashed red}
<b>1. example:</b>
<code>&lt;p&gt;&lt;br&gt;&lt;/p&gt;</code>
<p><br></p>
<b>2. example:</b>
<code>&lt;p&gt;I am a line&lt;br&gt;&lt;br&gt;&lt;/p&gt;</code>
<p>I am a line<br><br></p>
<b>3. example:</b>
<code>&lt;p&gt;&lt;/p&gt;</code>
<p></p>

The case in first example means that this represents a placeholder blank line. And this is not empty! Why? Because a placeholder blank line has some font size properties. In other case it would be like in third example – empty.

The case in the second example shows us two br elements on the end of block element and we can see that last br element was ignored, but the second br element from the end has his own line.

The user kalkronline has done the research again, but he has found wrong explanation wih misinterpretation from user Rei. The explanation from user Rei is only at the first look logical, but if we read what I wrote than we will see that he has done logical mistakes. My second example shows us user's Rei mistake because according to his description we would have to have an empty line. The cite from user's Rei misinterpretation:

Because the line has zero characters, it is rendered as an empty line.

But it is because no elements follows after it in this block element!

Conclusion

I would like to write some rules for your converter:

  1. If a paragraph consists of nothing but a single br element, it represents a placeholder blank line (from WHATWG recommendations)
  2. All br elements at the end of block elements if after them is nothing coming should be ignored.
  3. Only the last br element from two or more br elements on the end of block elements has to be ignored. But previous br elements have to have an own line with font size height.
  4. You have to follow all WHATWG recommendations.

Usefull links:

Please take a look at my more informed, updated answer.


Here's a W3 doc that states that browsers are expected to ignore empty p elements. The definition of "ignore" is kind of loose, so consider the following snippets:

<p>hello</p>
<p></p>
<p>hello</p>

It will render more or less the same as your code:

<p>hello<br /></p>
<p>hello</p>

That isn't to say that the elements are completely scrubbed from the page. Applying a style reveals that they've just been shrunk.

<p>hello<br style="margin-bottom: 100px"/></p>
<p>hello up there!</p>

Here is some more documentation and a few additional links which ask similar questions.

W3 doc on Whitespace

Change Height of Line Breaks

Empty Paragraph Tags

The <br> element has a single, well-defined purpose — to create a line break in a block of text.

A line break is defined to be a carriage return (&#x000D;), a line feed (&#x000A;), or a carriage return/line feed pair. All line breaks constitute white space.

https://www.w3.org/TR/REC-html40/struct/text.html#line-breaks


Let's brute force a test, to see which tags render the <br/> at the end, and which do not. https://jsfiddle.net/t7bnokzc/1/

We can see that these tags completely ignore the last <br/> as in they do not go to the next line, and show the text right next to them.

<button>
<canvas>
<img>
<iframe>
<input>
<ruby>
<meter>
<progress>
<select>
<svg>
<textarea>
<video>

Meanwhile these tags ignore the last <br/> :

<address>
<article>
<aside>
<audio> // Has a default height and width, differs from browser to browser
<blockquote>
<center>
<datalist>
<dd>
<details>
<dir>
<div>
<dl>
<dt>
<fieldset>
<figcaption>
<figure>
<footer>
<form>
<h1>
<header>
<legend>
<li>
<main>
<nav>
<ol>
<optgroup>
<option>
<p>
<pre>
<section>
<summary>
<ul>

What do these above have in common? They've got either a display:block or a display:list-item.

Conclusion :

If you put a line break at the end of an element that doesn't render line breaks (list above) or an element that at it's end there's an element that doesn't render line breaks it gets ignored.

Another example :

<address>Hello
  <b>ddg<br></b>
  <b>ddg<br></b>
</address>

Knowing that address tag is a block element, it behaves exactly as the p tag, knowing that the b tag behaves like the a tag : they render the last line break unless it ends inside a block element.

br element behaves like plain blocking element with 0 size, therefore in your cases it just adds 0px to the end of p (or a). When another text follows any blocking element, it will be placed under (Therefore creating line break). When there is no text, there is no extra space at the end.

This is common behavior for content-editable to place br on the end of each line, alongside with wrapping each line into p element

As mentioned in comments, implmentation may be different between browsers, but in the end logic is the same, blocking element with no size.

Why we use br tag - The HTML br element produces a line break in text (carriage-return). carriage-return or return is a control character or mechanism used to reset a device's position to the beginning of a line of text.

Point to Note:

If you check the dimensions of br tag, it has width = 0 and some height(~18px). But if you use it inside the p tag then br tag takes the height of p element but the important thing is its own width is 0.

Answer to your question

if we use it as = <p>Hello<br></p> then you will be able to see br element in developer console but no extra space, because we don't have any text after br tag and its own width is 0, so overall width becomes zero. Hence it does not take any extra space or line break. Example -

p {
  margin: 0;
}
<p>Hello<br></p>
<p>Hello<br></p>

But if we have code like this - <p>Hello<br>World</p> then br tag takes the cursor to beginning of the next line and we have text after br tag with some width. So, we will be able to see extra space or line break. Example -

p {
  margin: 0;
}
<p>Hello<br>World</p>
<p>Hello<br>World</p>

And I agree this is not the right place to use br tag because p element will automatically add a line break. So, using br tag just before end p tag makes no sense.

Please check below links:

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/br

https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-br-element

From what I have observed is that <br> elements cause trailing inline elements to be rendered onto the next line. In your case:

<p>Hello<br></p>
<p>Hello</p>

The <br> can't cause trouble to the sibling p tag because they are by default block elements. If you apply a bit of CSS:

p {
    display: inline;
}

You will see that your <br> tag will render the sibling <p> tag to render onto the next line.

I think it just boils down to display property of trailing element(s), if they are inline aka. in the text flow, those element(s) will find themselves under the effect of <br> otherwise, if there is any other renderable element(s) of different display property, they won't be affected by it.

As @karlkronline said, it might very well be true that the <br> elements mark the end of current line. And, if your next "visible" element to be rendered is an inline element, it moves to next line and render it. However, if of any other type, since elements are by default rendered on a separate line, there's no point to move again to the next line and render the element. It might just be enough to see that we will already be on the next line so, ignore and continue rendering.

To render an explicit <br> b/w block elements, use 2 <br>s. They will technically turn out to be just 1 line break. Why would it work? It would work because when first <br> marks it as next line, the renderer would encounter another <br> which is an inline element by default so, moving to next line makes sense. But, for the second <br> when it marks it as next line, the next element would be block, which will already be rendered on a separate line so, ignored.

Concluding, in the expression form:

<br> followed by <INLINE ELEMENT> = Next line starting with <INLINE ELEMENT>
<br> followed by <BLOCK ELEMENT> = Ignore since <BLOCK ELEMENT> will render on the next line anyway

Found this answer which gives an explanation much more elegant than I ever could come up with. I'll try to summarize and apply it to your situation. Let's take another look at your code.

<p>hello<br/></p>
<p>howdy</p>

<hr/>

<p>hello</p>
<p>howdy</p>

The code above and below the horizontal rule renders the exact same.

WHY?

Well, as user Rei explains, it's because "the BR element is not ignored at all. It marks that the line must be broken at that point. In other words, it marks the end of the current line of text. It is not about creating new lines." We know that it isn't ignored because we are able to apply styles to it. As I discovered earlier, making the margin larger than the default reveals that the break is still there.

Consider looking at the other answer for more details. The user who asked the question allegedly is making a similar program, and the answer has plenty of examples and documentation linked. p and div are both block level elements, so keep that in mind as you read the post.

TLDR: BR does not automatically make a newline, it just marks the end of the current line of text.

The <br> elements are always rendered in all browsers, since all browsers are aligned to follow a particular specification amended by the W3C Consortium, but in some instances their effects gets hidden.

You will understand, why it is so, when you get a deeper perspective on how the <br> and <p> tags work in this particular context of your question. So let us take a deeper look.

The <br> tag - When applied after a content, it leaves a line break, two <br> tags simultaneously can leave a single line of space between visible texts as seen between paragraphs. Note: By virtue of design of <br> tags, every subsequent <br> tag after two consecutive <br> tags will insert a single line of empty space(Note: A single line of empty space is conventionally known as a paragraph break) instead of a line break.

The <p> tag - It does ensure that, there is an empty line of space on either side of the embedded content(Note: The empty lines of space within the content that precedes or succeeds it, are treated as part of the content itself). It does not take into account of any line breaks ( Note: It takes two line breaks to leave an empty line of space(Paragraph Break) ie; 2 <br> tags & every subsequent <br> tags after 2 consequent <br> tags insert a line of empty space instead of a line break.).

Take a look at the following code snippets.

1.

<p>This is a paragraph.</p>
This is a paragraph.

In the above code snippet, see that the first line of text is within the <p> tag while the second line is not, and it functions as i described above.

2.

<p>This is a paragraph.</p>
<p>This is a paragraph.</p>

In the above code snippet, both the texts are embedded within 2 separate <p> tags, still there is only a single line of empty space between them. This is because the <p> tag will only consider the empty lines of space that are part of the text/content while leaving its own empty line of space. You'll get more clarity as you examine the code snippets below.

3.

<p>This is a paragraph.<br></p>
<p>This is a paragraph.</p>

In the above code snippet, a single <br> tag is embedded within the first <p> tag, but see that a single <br> is not equivalent to an empty line of space( it takes 2 <br> tags to be equivalent to an empty line of space). So an empty line of space is not part of our first text content so you will not see the effect of <br> tag, as a single line break is not equivalent of a line of space & <p> tag only takes into account of preceding lines of space before inserting its own single line of space. By virtue of design, the <p> tag will consider the empty lines of space within an element as part of that element, so in case an element has empty lines of space towards its end then the <p> tag still leaves its own single line of empty space thus adding an extra blank line to the already existing lines of spaces of the content, Look at the example that follows.

4.

<p>This is a paragraph.<br><br></p>
<p>This is a paragraph.</p>

In the above code snippet, 2 <br> tags have been inserted inside the first <p> tag so it leaves an empty line of space as part of the first <p> tag. The second <p> tag will consider this empty line of space as a part of the content within the first <p> tag and when it insert its own single line of space after the previous content, it seems as if an extra blank line of space have been added to it.

5.

<p>This is a paragraph.<br><br><br></p>
<p>This is a paragraph.</p>

In the above code snippet, you can see 3 <br> tags are part of the first <p> tag, now scroll up and look at the functioning of <br> tags as i described in the begining, you can see that now 2 lines of empty space are part of the content inside first <p> tag, hence the spacing between the either <p> tags are of 3 lines of empty space(2 empty lines by virtue of 3 <br> tags and 1 empty line by virtue of the succeeding <p> tag).

Hope this address your doubt, please also do refer this BR tag has no effect when parent has height, to get a different perspective.

Related