Reputation: 1839
I have a <button>
element and within it, a <p>
element. The <p>
element is used in combination with css, margin-top
, in a class to vertical align the text within the button (the button has a specific height).
The html looks like this:
<button class="someClass">
<img ... />
<p class="anotherClass">Caption</p>
</button>
This works fine, the text is vertically aligned like it should be. However I get a warning inside visual studio 2012 saying:
Element 'p' cannot be nested inside element 'button'.
My questions: why isn't the <p>
element allowed inside a <button>
element? And what is the alternative?
Upvotes: 12
Views: 25959
Reputation: 11
Since the p
and some other tags cannot be used within the button
tag, the best workaround, as others have stated, is to use a styled span
tag.
You treat the button
tag "as if" it was a container div
of your span
tags within. That way, you can style your whole button
however you want. In my example, I styled it with a simulated icon, title, description, and button within the button.
I'm adding a little extra styling and formatting for visual purposes, but yours can be as simple or complex as you want.
/* CSS Styling and classes example */
/* style the main container */
button {
background-color: transparent;
outline: none;
border: none;
cursor: pointer;
transition: 0.2s;
padding: 10px 15px;
}
/* what happens when you hover - optional */
button:hover {
background-color: #efefef;
}
/* what happens when it's active - optional */
button.active {
background-color: #ccc;
}
/* global style for the contained span tags within */
button span {
display: block;
margin: 5px auto 10px;
}
/* individually styling the inner span tags by class identifiers */
button span.step {
background: #c33;
color: #fff;
padding: 10px 2px 0 0;
font-size: 1.75em;
font-weight: 600;
width: 40px;
height: 40px;
border-radius: 20px;
}
button span.title {
font-size: 2em;
font-weight: 600;
}
button span.desc {
font-size: 1.05em;
}
button span.btn {
margin: 20px auto;
padding: 5px 10px;
background: #c33;
color: #fff;
}
<!-- html code -->
<button class="customClass">
<span class="step">1</span>
<span class="title">Title</span>
<span class="desc">My cool button description</span>
<span class="btn">Click Here</span>
</button>
Of course, you can modify, add and remove span elements as you see fit, including images.
Upvotes: 0
Reputation: 288080
That is correct, it isn't allowed, because;
button
element is phrasing content (with no interactive content descendant).p
can only be used where flow content is expected.An alternative is getting rid of the p
element, and instead using a span
element with display: block
:
.anotherClass {
display: block;
}
<button class="someClass">
<img ... />
<span class="anotherClass">Caption</span>
</button>
Upvotes: 27
Reputation: 201558
Visual Studio is correct in this issue: no HTML specification allows p
in button
, not even the rather liberal definition in HTML5 CR.
However, browsers do not actually enforce this restriction (in the sense that they enforce e.g. the restriction that span
cannot contain p
: they implicitly close an open span
element when they see a <p>
tag). So your code “works”, though there is really no guarantee that it will keep working (or that it works on all browsers).
To make the code formally valid, replace the p
element by a span
element and style it. You might also put a <br />
tag before it, to ensure a line break even when CSS is disabled. To set a top margin on it, make it a block or an inline block. Example:
.anotherClass {
display: block;
margin-top: 1em;
}
<button class="someClass">
<img src="http://lorempixel.com/100/50" alt="Some text" /><br />
<span class="anotherClass">Caption</span>
</button>
Upvotes: 2
Reputation: 4540
Generally you're not supposed to put block elements inside of inline elements.
Upvotes: 3