How to Nest Button Inside Another Button

Can I nest button inside another button?

It is not valid to put a <button> inside a <button> element.

In the W3C recomendation for the button element you can read:

Content model:

Phrasing content, but there must be no interactive content descendant.

[source: w3.org (emphasis mine)]

Interactive content includes:

  • a
  • audio (if the controls attribute is present)
  • button
  • embed
  • iframe
  • img (if the usemap attribute is present)
  • input (if the type attribute is not in the hidden state)
  • keygen
  • label
  • object (if the usemap attribute is present)
  • select
  • textarea
  • video (if the controls attribute is present)

Accessible nested button inside button?

Preword

Don't nest interactive elements

There is a reason that it isn't valid HTML to nest buttons or hyperlinks, it causes nightmares for knowing which action should be performed on a click (for a start) and for assistive technology this makes things even worse as it can confuse the accessibility tree as to what it should present to screen readers.

The answer

If you look carefully you will see they aren't actually nested, the "picker" button is placed on top of the other button.

Now there is an issue here in terms of accessibility, click / tap target size.

A button / interactive element should be no less than 44px by 44px

So the Zoom example you gave fails this criteria. Additionally the tooltip that says "stop video" looks wrong if you have the picker selected as that should be the tooltip for the button that is currently hovered.

So how could we create an accessible version of what you want?

I would recommend having a large button with a 44 by 44 button placed on top to the right.

This can easily be done with absolute positioning.

To ensure that it is evident visually that the buttons are related I inset the second button by 2px.

The below is not a complete example but I have given you a start.

I added aria-expanded to the button that opens the sub menu, this gets toggled when the menu is opened.

I also added the aria-haspopup attribute to let users know that this button opens a sub menu.

I also added aria-controls to let assistive technology know the relationship between the button and the menu it opens.

Finally you will see I added a <span> with some visually hidden text inside so that screen reader users know that the picker button opens the video controls.

The example maintains logical tab order and is pretty accessible, but there are still things such as being able navigate the menu buttons with the arrow keys, closing the menu with Esc key and returning focus to the button that opened the menu etc. that you need to implement yourself. Oh and styling obviously!

var mainButton = document.querySelector('.main-button');
var menuToggle = document.querySelector('.sub-button');
var menu = document.getElementById('controls');

mainButton.addEventListener('click', function(){

alert("clicked the main button");
});

menuToggle.addEventListener('click', function(){

if(menu.classList.contains('open')){
menu.classList.remove('open');
menuToggle.setAttribute('aria-expanded', false);
}else{
menu.classList.add('open');
menuToggle.setAttribute('aria-expanded', true);
}
});
.container{
position: relative;
width: 144px;
height: 48px;
}
.main-button{
width: 144px;
height: 48px;
padding-right: 50px;
}
.sub-button{
position: absolute;
width: 44px;
height: 44px;
top:2px;
right:2px;
}
.visually-hidden {
border: 0;
padding: 0;
margin: 0;
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 - a 0 height clip, off to the bottom right of the visible 1px box */
clip: rect(1px, 1px, 1px, 1px); /*maybe deprecated but we need to support legacy browsers */
clip-path: inset(50%); /*modern browsers, clip-path works inwards from each corner*/
white-space: nowrap; /* added line to stop words getting smushed together (as they go onto seperate lines and some screen readers do not understand line feeds as a space */
}
#controls{
display: none;
}
#controls.open{
display: block;
}
<div class="container">
<button class="main-button">Stop Video</button>
<button class="sub-button" aria-expanded="false" aria-haspopup="true" aria-controls="controls">⌄ <span class="visually-hidden">Pick Device</span></button>
<ul id="controls"
role="menu"
aria-labelledby="sub-button">
<li><button>Option 1</button></li>
<li><button>Option 2</button></li>
</ul>
</div>

Nested buttons in HTML

You should not add button inside another button. It is wrong syntax.

Try to use div instead of button.

<div style="height:750px; width:750px; border:1px solid black;">Click here
<button style="height:50px; width:50px">a</button>
<button style="height:50px; width:50px">b</button>
<button style="height:50px; width:50px">c</button>
<button style="height:50px; width:50px">d</button>
</div>

Demo Here: https://jsfiddle.net/swpm3aL1/3/

Can I nest button inside of a

Something like this:

<div class="container">
<a class="button7" href="http://google.co.uk" onmouseover="displayFavorite('000')" onmouseout="hideFavorite('000')">
Math 141

<ul>
<li><strong>Description</strong> Calculus 1 and Calulus 2</li>
<li><strong>Instructor</strong> Boon Ong</li>
<li><strong>Documents</strong> 17</li>
</ul>
</a>
<button id='000' class="button8" onclick="favorite('000')">Favorite</button>
</div>

CSS:

.container {
position:relative;
width:400px;
}
.button7 {
width:100%;
height:auto;
display:block;
background:red;
}
.button8 {
position:absolute;
top:5px;
right:5px;
}

Positioning an element absolutely in a parent container with position:relative; enables you to use the css properties top, left, right, and bottom relative to the container that encloses it.

Setting the <a> (with class .button7) to display:block; means that the hyperlink will act as a block level element and take up the entire "block" (i.e. space afforded to it by its parent)

http://jsfiddle.net/t29m4/

Nested button in a tag with different onClick event

You can add the event token to the onClick event and use e.preventDefault() to override the anchor tag event:

function someFunction(e) {
e.preventDefault()
console.log('some function executed')
}
<a href='/path/to/somewhere' >
<div>
<div>Element 1</div>
<div>Element 2</div>
<div>Element 3</div>
<button onClick='someFunction(event);' >Click Me</button>
</div>
</a>

Can I nest a button element inside an a using HTML5?

No, it isn't valid HTML5 according to the HTML5 Spec Document from W3C:

Content model: Transparent, but there must be no interactive content descendant.

The a element may be wrapped around entire paragraphs, lists, tables, and so forth, even entire sections, so long as there is no interactive content within (e.g. buttons or other links).

In other words, you can nest any elements inside an <a> except the following:

  • <a>

  • <audio> (if the controls attribute is present)

  • <button>

  • <details>

  • <embed>

  • <iframe>

  • <img> (if the usemap attribute is present)

  • <input> (if the type attribute is not in the hidden state)

  • <keygen>

  • <label>

  • <menu> (if the type attribute is in the toolbar state)

  • <object> (if the usemap attribute is present)

  • <select>

  • <textarea>

  • <video> (if the controls attribute is present)


If you are trying to have a button that links to somewhere, wrap that button inside a <form> tag as such:

<form style="display: inline" action="http://example.com/" method="get">
<button>Visit Website</button>
</form>

However, if your <button> tag is styled using CSS and doesn't look like the system's widget... Do yourself a favor, create a new class for your <a> tag and style it the same way.

Nested button inside div

In the function handling the click event for the inner div, stop the event from propagating to the outer div by calling event.stopPropagation() on the event:

function clickHandler(event) {
event.stopPropagation();

// Do your other stuff like Ajax calls
}


Related Topics



Leave a reply



Submit