47

I know it's wrong to put a block element inside an inline element, but what about the following?

Imagine this valid markup:

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

Now add this CSS:

div {
   display:inline;
}

This creates a situation where an inline element contains a block element (The div becomes inline and the p is block by default)

Are the page elements still valid?

How and when do we judge if the HTML is valid - before or after the CSS rules are applied?

UPDATE: I've since learned that in HTML5 it is perfectly valid to put block level elements inside link tags eg:

<a href="#">
      <h1>Heading</h1>
      <p>Paragraph.</p>
</a>

This is actually really useful if you want a large block of HTML to be a link.

Matthew James Taylor
  • 4,806
  • 5
  • 29
  • 33
  • 3
    I'm glad html5 considers this valid, but valid code isn't the end-all be-all of the web. The Googles uses code that looks like horribly broken tag soup, but it works. – JKirchartz Feb 10 '12 at 21:06

9 Answers9

31

From the CSS 2.1 Spec:

When an inline box contains an in-flow block-level box, the inline box (and its inline ancestors within the same line box) are broken around the block-level box (and any block-level siblings that are consecutive or separated only by collapsible whitespace and/or out-of-flow elements), splitting the inline box into two boxes (even if either side is empty), one on each side of the block-level box(es). The line boxes before the break and after the break are enclosed in anonymous block boxes, and the block-level box becomes a sibling of those anonymous boxes. When such an inline box is affected by relative positioning, any resulting translation also affects the block-level box contained in the inline box.

This model would apply in the following example if the following rules:

p    { display: inline }
span { display: block }

were used with this HTML document:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<HEAD>
  <TITLE>Anonymous text interrupted by a block</TITLE>
</HEAD>
  <BODY>
    <P>
      This is anonymous text before the SPAN.
      <SPAN>This is the content of SPAN.</SPAN>
      This is anonymous text after the SPAN.
    </P>
  </BODY>

The P element contains a chunk (C1) of anonymous text followed by a block-level element followed by another chunk (C2) of anonymous text. The resulting boxes would be a block box representing the BODY, containing an anonymous block box around C1, the SPAN block box, and another anonymous block box around C2.

The properties of anonymous boxes are inherited from the enclosing non-anonymous box (e.g., in the example just below the subsection heading "Anonymous block boxes", the one for DIV). Non-inherited properties have their initial value. For example, the font of the anonymous box is inherited from the DIV, but the margins will be 0.

Properties set on elements that cause anonymous block boxes to be generated still apply to the boxes and content of that element. For example, if a border had been set on the P element in the above example, the border would be drawn around C1 (open at the end of the line) and C2 (open at the start of the line).

Some user agents have implemented borders on inlines containing blocks in other ways, e.g., by wrapping such nested blocks inside "anonymous line boxes" and thus drawing inline borders around such boxes. As CSS1 and CSS2 did not define this behavior, CSS1-only and CSS2-only user agents may implement this alternative model and still claim conformance to this part of CSS 2.1. This does not apply to UAs developed after this specification was released.

Make of that what you will. Clearly the behaviour is specified in CSS, although whether it covers all cases, or is implemented consistently across today's browsers is unclear.

Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
Alohci
  • 78,296
  • 16
  • 112
  • 156
  • Just for clarification, it seems to me it is not wrong but part of the css specification that you 'can'. It requires extra work on the browser to create anonymous blocks. Also not consistent across web browsers. – Chad Jun 25 '13 at 02:21
  • 1
    Hello @Alohci. I've got a situation that goes something like ``. Here all elements have their normal display properties, however I use the `::after pseudo-element` with ``, with some text content and I set that pseudo-element to block. That element is a child of `span` which is a child of `a` which is a child of `div`. Since inline elements don't support width, how is the width 100% from being a block type work here ? I feel like I'm in this Anonymous box scenario, can you point me in the right direction? Thx – Marius Mucenicu Apr 02 '19 at 06:13
  • 2
    @George - You'll often see statements like "block elements [in normal flow] take 100% of their parent's width". That's not in fact correct. If you look at section [10.3.3 Block-level, non-replaced elements in normal flow](https://www.w3.org/TR/CSS22/visudet.html#blockwidth) you'll see that it's really "block elements [in normal flow] take 100% of their **containing block**'s width". Inline elements like your span are not block containers. Instead the nearest ancestor element that is a block container (i.e. your div element) is used to establish the 100% width. – Alohci Apr 02 '19 at 08:28
  • @Alohci makes perfect sense. Thanks sir! – Marius Mucenicu Apr 02 '19 at 12:05
  • hi @Alohci +1. In the example you gave, the text "This is anonymous text before the SPAN." and the text " This is anonymous text after the SPAN.", what type of anonymous box are they, block box or inline box? –  Apr 16 '23 at 03:11
  • 1
    @GeorgeMeijer - Strictly speaking, neither, but it's quite subtle. For the purposes of the above quoted text, the contents of the body element are split into three block boxes, which contain: 1. The section of the P element before the span; 2 The span; 3 The section of the P element after the span. 1 and 3 are **anonymous block boxes**. The texts directly inside the P element (e.g, "This is anonymous text before the SPAN.") are inside a **named** inline box (i.e. named "P"), so there is no need for any anonymous inline boxes. – Alohci Apr 16 '23 at 03:58
  • "*The texts directly inside the P element (e.g, "This is anonymous text before the SPAN.") are inside a named inline box (i.e. named "P"), so there is no need for any anonymous inline boxes*" - This is because anonymous block boxes **behave like "normal" block boxes**, i.e. inline boxes (in this case the texts "This is anonymous text before the SPAN." and "This is anonymous text after the SPAN.") and other block boxes **see these as non-anonymous block boxes**, right? @Alohci –  Apr 16 '23 at 19:20
  • That is to say, what is being asked here in this question https://stackoverflow.com/questions/75843901/can-an-anonymous-block-box-create-an-inline-formatting-context-like-that-created @Alohci –  Apr 16 '23 at 19:21
  • @GeorgeMeijer - For that linked question, Temani's comment is correct. But what you're asking in the comment above does not seem correct. Text sequences are not boxes at all. They are seen as **inline content**. This is clearer in the [CSS Display Level 4 spec](https://drafts.csswg.org/css-display-4/#intro) than in the CSS 2.2 spec and I strongly encourage you to read section 1 of that and also section 2 of the [CSS Inline Layout Level 3 spec](https://drafts.csswg.org/css-inline-3/#model) as they make significant clarifications and corrections to what you might read in CSS 2.2 – Alohci Apr 16 '23 at 19:43
15

Regardless if it's valid or not, the element structure is wrong. The reason that you don't put block elements inside inline elements is so that the browser can render the elements in an easily predictable way.

Even if it doesn't break any rules for either HTML or CSS, still it creates elements that can't be rendered as intended. The browser has to handle the elements just as if the HTML code was invalid.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • 4
    so then what do you do, when you need a whole row in a table to be clickable? – mgPePe Mar 10 '12 at 18:57
  • 2
    @mgPePe: There are several options. You can put a link in every cell in the row, you can use Javascript to catch the click event on the row, or you can use something different from a table. – Guffa Mar 11 '12 at 12:42
  • Yes, JS is a good solution. What I ended up doing was to have an `a` with nested `span display="block"` according to this example: http://www.jakpsatweb.cz/css/css-vertical-center-solution.html – mgPePe Mar 12 '12 at 08:03
  • 4
    @Guffa I downvoted, because it seems odd to me to simply assert that something is 'wrong' despite the spec stating that it is valid, and I can't tell from your answer when - if ever - the correct behaviour by the browser would be unclear. Perhaps there's something I'm missing, but it's not clear to me after reading this that the claim that *"it creates elements that can't be rendered as intended"* is true, or even what that means. – Mark Amery Apr 12 '15 at 17:35
  • @MarkAmery: The spec doesn't state that it's valid. – Guffa Apr 12 '15 at 19:28
5

The HTML and the CSS will both still be valid. Ideally, you wouldn't have to do something like this, but that particular bit of CSS is actually a handy (and syntactically valid but not semantically valid) way for getting Internet Explorer's double margin bug without resorting to conditional stylesheets or hacks that will invalidate your CSS. The (X)HTML has more semantic value than the CSS, so it's less important that the CSS is semantically valid. In my mind, it's acceptable because it solves an annoying browser issue without invalidating your code.

VirtuosiMedia
  • 52,016
  • 21
  • 93
  • 140
1

The HTML is validated independently of the CSS, so the page would still be valid. I'm fairly sure that the CSS spec says nothing about it either, but don't quote me on that one. However, I'd be very careful using a technique like this, as while it might render as intended in some browsers, you'd need to test 'em all—I don't see many guarantees being made.

Samir Talwar
  • 14,220
  • 3
  • 41
  • 65
1

Are the page elements still valid?

“Valid” in an HTML sense, yes; HTML knows nothing about CSS.

The rendering you get in the browser, however, is ‘undefined’ by the CSS specification, so it could look like anything at all. Whilst you could include such a rule in CSS hacks aimed at one particular browser (where you know how that browser renders this case), it shouldn't be served to browsers in general.

bobince
  • 528,062
  • 107
  • 651
  • 834
0

I don't know off the top of my head if this validates any rules but I would recommend using the W3C HTML Validator and the W3C CSS Validator to determine that. Hope this is helpful!

Adam Alexander
  • 15,132
  • 5
  • 42
  • 41
-1

If there is a logic you follow and you end up implementing it like this, it's NOT WRONG. Working things are not "wrong" just because they're weird. Yes, it's quite unusual but it HELPS and it's not a mistake. It's intentional. HTML and CSS should serve you, not the other way around so don't ever listen to comments telling you not to do it just because it's ugly.

It's typical to call a solution "invalid" and suggest a long way around the block. Sometimes you can rethink what you did. But there can be many reasons for what you did and they don't consider them.

I do use blocks inside inlines regularly. It's valid and it's working - it's just not necessary in most cases. So what. Remember when XHTML told us to always put quotes around properties (and everyone yelled at you if you didn't!), now HTML5 allows to omit them if there's no space inside. What happened to that last slash after singular tags? "<br />" ? Come on. Standards change. But browsers keep supporting non-standard things as well. CENTER is deprecated; we're in 2013 and it still works. TABLE for vertical centering? Sometimes it's the only way. DIV inside A to make it hover as you planned? Just go ahead.

Focus on important things.

dkellner
  • 8,726
  • 2
  • 49
  • 47
-2

I think, (x)html is valid, css is valid. Is the result valid? Yes, if it is looking in the browser as You want.

Sergei Kovalenko
  • 1,402
  • 12
  • 17
  • 1
    The problem with using browsers to validate the code is that you need to revalidate the page for every new version of every browser on every system where you want the page to work... – Guffa Apr 14 '09 at 07:37
  • Yes, that is real problem, I know. Browser is not validator :) And I think, question about HTML+CSS result validating is a question of taste. Human factor. – Sergei Kovalenko Apr 15 '09 at 10:33
-3

No, It is not a wrong choice. We can use as per requirements.