HTML Input and Labels
Input and labels work together to create writable text fields or clickable buttons. These are often used in combination with javascript to create submittable forms. They also are particulary helpful for adding a mobile optimized menu that uses CSS to appear or disappear when it is turned on or off.
<nav>
<input type="checkbox" id="menu-toggle" role="button">
<label for="menu-toggle" class="menu-toggle">☰
</label>
<ul id="menu">
<li><a href="page1.html">Menu Item 1</a></li>
<li><a href="page2.html">Menu Item 2</a></li>
<li><a href="page3.html">Menu Item 3</a></li>
</ul>
</nav>
The order and placement of HTML elements is extremely important as it determines how complex the selector needs to be for the CSS to work properly later on. The following order is always easy to work with and is recommended when starting out:
- Input - the button that actually turns the menu on and off
- Label - the visual representation of the button that turns the menu on and off
- List of menu items/links - place directly after the label
Sometimes you might have a more complex behavior that you are trying to achieve that requires a different order. Input must always be first, either literally in the HTML or occassionally through reversing the direction with flex in the CSS. There is more flexibility in where to place the label and the menu itself, as long as they are placed after the input. They don't necessarily need to be kept together.
Turning the Menu "On" & "Off" with CSS
There are many potential techniques to show/hide the menu. Always choose carefully. Some techniques, like changing the z-index, might have accessibility issues with screenreaders & etc.
Using position is often a great way to start. Position is animatable, compatible with screen readers, and doesn't have a negative impact on search engine optimization.
nav {position:relative;}
nav ul {position:absolute; width:100%; z-index:10;}
nav input {display: none;}
#menu-toggle:checked ~ ul {left:0px;}
#menu-toggle:not(checked) ~ ul {left:-1000px;}
- nav list style:
- relative position - helps control the location of the menu
- menu list styles:
- absolute position - takes the menu out of the flow of the page so that it displays on top
- z-index - guarantees the menu displays over other content
In this example, the menu is moved offscreen to left only when the input is not checked. This could just as easily be moved above the top, right or bottom. If there was a set width for the list (ie. ul {width:200px;}), it might make more sense to move the menu only the distance of the width (ie. #menu-toggle:not(checked) ~ ul {left:-200px;})
For the selectors, take advantage of how the general sibling ~ or adjacent sibling + selectors work. General siblings ~ can be used to select any sibling element that follows (within the same parent, at the same level). Adjacent siblings + select only the next sibling element and ignores any following siblings.
Adding Flex and Media Queries
Adding Transitions
Using Input/Labels to create tabs
The basic setup for creating tabs is very similar to working with the advanced menu.
The HTML
- Exact location/placement might change, but the general order of elements should be input → label → element for changing content
- Input Type = radio (this way the input are linked together and only one can be active)
- Add "checked" to the end of one of the input (this will control what is visible by default when the page loads after adding some additional CSS)
- Placing the labels in a
section (or other element) allows the labels to easily be placed side by side with future CSS
<input name="tabs" id="tab1" type="radio" checked>
<input name="tabs" id="tab2" type="radio">
<section>
<label for="tab1">Tab 1</label>
<label for="tab1">Tab 1</label>
</section>
<div id="content1">
...changing content here...
</div>
<div id="content2">
...changing content here...
</div>
CSS
The following just has the CSS for the first input - but it would be the same for any additional input, just with different id numbers. If the HTML is organized differently, the CSS might change in response.
input#tab1:checked ~ section label[for="tab1"] {background-color:...}
input#tab1:not(:checked) ~ section label[for="tab1"] {background-color:...}
input#tab1:checked ~ #content1 {display: flex;}
input#tab1:not:(checked) ~ #content1 {display: none;}
section {display:flex;}
HTML+CSS Simplified
If each input/label/content element are placed directly together with nothing between on the HTML side, the CSS selectors can be simplified a lot — so that ids aren't even necessary as part of the selector. In this case, absolute or fixed positioning might be used to control the placement of the labels.
<input name="tabs" id="tab1" type="radio" checked>
<label for="tab1">Tab 1</label>
<div id="content1">
...changing content here...
</div>
<input name="tabs" id="tab2" type="radio">
<label for="tab1">Tab 1</label>
<div id="content2">
...changing content here...
</div>
input:checked + label {background-color:...}
label {position: absolute; top:...left:...}
input:not(:checked) + label {background-color:...}
input:checked + label + div {display: flex;}
input:not:(checked) + label + div {display: none;}