27

My company is building a website and we had some problems with a JavaScript library not replacing something. We decided to throw our HTML in to the W3C validator and it informed us it's illegal to have a <div> tag inside a <button> tag.

<button class="button" type="submit">
    <div class="buttonNormalLargeLeft"><!--#--></div>
    <div class="buttonNormalLargeCenter">Search Flights</div>
    <div class="buttonNormalLargeRight"><!--#--></div>
</button>

Results in:

Line 287, Column 46: Element div not allowed as child of element button in this context. (Suppressing further errors from this subtree.)

Edit: To clarify what we're trying to do here. We want to make a button with rounded corners that doesn't rely on box-radius. We made 3 divs in the button element each has his own sprite to make it appear rounded and allow for different widths. Other resources state that the button element was created for users that wanted a button to contain sub elements such as images but divs appear to be invalid for some reason.

Why are divs not allowed inside button elements?

What is the desired solution to this issue?

Edit2:

Why not use input? Because inputs can't have the desired layout

Why not use divs? Because users without JavaScript won't be able to submit the form.

TFennis
  • 1,393
  • 1
  • 14
  • 23
  • What are you trying to do? It seems there is a better way. What's wrong with using button normally? I don't understand what you're trying to accomplish here. are you trying to center your label? – Thomas Wright Apr 08 '13 at 17:44
  • http://www.w3schools.com/tags/tag_button.asp – Thomas Wright Apr 08 '13 at 17:44
  • @Thomas Wright The css classes have separate images to give the button rounded corners. We do not want to use the CSS property for this yet. – TFennis Apr 08 '13 at 17:46
  • 12
    It's not a bad question, what you're doing is actually widely used, (one of the benefits of the ` – RestingRobot Apr 08 '13 at 17:50
  • You could use a `div` for the button, display & submit with JS, then use a standard button in ` – JKirchartz Apr 08 '13 at 22:50
  • @TFennis - the reason we have js and css is to add functionality and capability to [x]html. Have you solved your problem yet? I would recommend that you not shy from such utilities. They have become an integral part of web design and development. Despite the general consensus in this thread, you can keep to w3c standards, xbrowser compatibility, and make it look exactly the way you want. Don't worry about that <.0001 percent that have jilted their technical experience and turned off js and don't be turned off by css. If [x]html was a picture, css would be the color. – Thomas Wright Apr 12 '13 at 18:17
  • How about just adding an `` tag inside your `button`? Validates and you get to create your button with rounded edges without `box-radius` and will work on any browser. – Wild Beard Mar 25 '15 at 19:29
  • 5
    Instead of *div*s, use *span*s with css of *display:inline-block*, so that you can size them. – Patanjali Oct 24 '16 at 00:43

5 Answers5

4

Well I posted a comment but no love.

You can achieve a W3C valid button by simply putting an image inside the button.

Fiddle

Granted you'll have to create your images and add the text to them. But since you've already created images for the corners that shouldn't be too hard.

Also image sprites are a great thing.

.test {
  width: 258px;
  height: 48px;
  background: none;
  border: 1px solid transparent;
}
.test:active {
  outline: 0;
}
.test > img {
  width: 258px;
  height: 45px;
  opacity: 1;
  background: url('http://www.copygirlonline.com/wp-content/plugins/maxblogpress-subscribers-magnet/lib/include/popup1/images/btn/blue-button.png');
  background-position: -3px 0px;
}
.test > img:hover {
  background-position: -3px -50px;
}
<button class="test">
  <img src="http://alistapart.com/d/cssdropshadows/img/shadowAlpha.png" />
</button>

If you want to stick with 3 images here's an updated version.

button {
  margin: 0;
  padding: 0;
  border: none;
}
<button>
  <img src="http://placehold.it/50x50" /><img src="http://placehold.it/50x50" /><img src="http://placehold.it/50x50" />
</button>

Also, without additional CSS, it seems you need to keep all of the <img /> tags on the same line or it treats the images as having space between them.

Neuron
  • 5,141
  • 5
  • 38
  • 59
Wild Beard
  • 2,919
  • 1
  • 12
  • 24
  • 1
    This is obviously a pretty old question of mine, and I'd love to approve an answer but... The reason we used 3 images is because the buttons needed to be able to have variable width. Using a single image plus stretching will give it weird corners. Althought I think your solution is probably possible if you just include 3 images in a – TFennis Jul 04 '16 at 11:55
4

Per the HTML standard a <button> may only contain Phrasing content. A div element is not a valid element for Phrasing Content.

andersra
  • 1,103
  • 2
  • 13
  • 33
2

If you want to use a custom button, you'll have to replace the button tag with a div or an input. It looks like a div is what you want in this case. You'll just have to add any necessary event handlers, (for your submit).

This might help clarify things a bit.

Community
  • 1
  • 1
RestingRobot
  • 2,938
  • 1
  • 23
  • 36
  • Like I commented above, we want buttons with rounded corners in browsers that do not yet support `border-radius` such as IE8. The 3 divs all have their own image. – TFennis Apr 08 '13 at 17:52
  • The input element does not allow rounded corners, and divs do not function as buttons for users without javascript. – TFennis Apr 08 '13 at 18:11
  • 2
    @TFennis You stated in your question that you were using Javascript. So why can't you use it here? – RestingRobot Apr 08 '13 at 18:26
  • FYI for anyone who happens upon this answer that changing a `button` to a `div` will break accessibility and should be avoided, and if you must do it then make sure to use the correct aria attributes and follow the accessibility guidelines to do so. – maxshuty Jul 14 '22 at 15:07
1

If you're using a form, you could change the button to be a clickable div instead. For example:

<div role="button" onclick="$(this).closest('form').submit()">
    <!-- your child content here -->
</div>

Alternatively, if you know the form name or ID you could change the inline javascript to something like document.getElementById("form-id").submit()

Jonathan
  • 10,936
  • 8
  • 64
  • 79
0

Suuuuper old question, but since I found it while searching for this answer myself, you can achieve this with a slight html re-structure and some simple CSS. Make the button the last child of a parent div, make it cover the div, and make it transparent.

I'm assuming you finished your website 9 years ago, but I'll explain this in full anyway in case others stumble across this in another 9 years.

HTML

<div class="buttonParent">
    <div class="buttonNormalLargeLeft"><!--#--></div>
    <div class="buttonNormalLargeCenter">Search Flights</div>
    <div class="buttonNormalLargeRight"><!--#--></div>
    <button class="button" type="submit"></button>
</div>

CSS

.button{
  position: absolute;
  left: 0px;
  top: 0px;
  width: 100%;
  height: 100%;
  background: transparent;
  border: none;
}

You could also use opacity: 0 instead of a transparent background and no border, but that removes your ability to tab to it.

You still have access to .button:hover, .button:active and .button:focus for the button itself, which can be used, for example, to add a background to the button itself with a very low opacity for a simple hover effect.

Or, if you want to go a little further down the rabbit hole, you can directly add or replace classes on the parent object, this will allow you to overwrite the previous classes and do whatever you want to the display of the button.

Non-JS

<button class="button" 
onclick="this.parentElement.classList.replace('buttonParent', 'buttonParentClicked')" 
onblur="this.parentElement.classList.replace('buttonParentClicked', 'buttonParent')"
type="submit"></button>

For example, ".buttonParentClicked .buttonNormalLargeLeft" will override the CSS you have for .buttonNormalLargeLeft, so you can use it to completely change the images and styles you have there.

And of course, if that's still not enough and you need more functionality on the parent, you can do whatever you want with JS.

HTML

<button class="button" onclick="myFunction()" type="submit"></button>

JS

myFunction(e){
    const parent = e.target.parentElement;
    //whatever you want to parent;
}
  • I appreciate an answer so many years later. Your answer works but to provide some extra context. At the time this question was asked I'm not sure all those CSS tricks were universally supported. We were still concerned with IE6 or whatever people used 9 years ago. Today there are many ways to accomplish the effect we were looking for in a much more idiomatic way. – TFennis Aug 26 '22 at 22:14
  • And I appreciate the response! It did occur to me after I went to bed that that may be the case! Not sure if this would have worked then or not! I just figured that since I needed to do this research for myself anyway and found your question while trying to find the answer myself, I would share it for future searchers! – MonsterBasket Aug 26 '22 at 23:20