This menu reveals an icon's name on click using radio buttons and CSS only. It could be useful as an app type menu or as iconified tabs.
A Pen by Ryan Smith on CodePen.
<div class="positioner"> | |
<div class="menu"> | |
<div class="menu_title"> | |
Fancy Icon Menu | |
</div> | |
<div class="menu_item"> | |
<input class="toggle" name="menu_group" id="sneaky_toggle" type="radio"> | |
<div class="expander"> | |
<label for="sneaky_toggle"><i class="menu_icon fa fa-bomb"></i> <span class="menu_text">Da Bomb</span></label> | |
</div> | |
</div> | |
<div class="menu_item"> | |
<input class="toggle" name="menu_group" id="sneaky_toggle2" type="radio"> | |
<div class="expander"> | |
<label for="sneaky_toggle2"><i class="menu_icon fa fa-bell"></i> <span class="menu_text">Da Bell</span></label> | |
</div> | |
</div> | |
<div class="menu_item"> | |
<input class="toggle" name="menu_group" id="sneaky_toggle3" type="radio"> | |
<div class="expander"> | |
<label for="sneaky_toggle3"><i class="menu_icon fa fa-child"></i> <span class="menu_text">Da Kid</span></label> | |
</div> | |
</div> | |
</div> | |
</div> |
// This box must be useful for something... how about some extra comments? | |
// This is a css only solution to an expanding menu | |
// It uses radio buttons and... | |
// These standard CSS "tricks" | |
// the :checked css pseudo class | |
// max-width transition effect | |
// Block, float:left is used for menu items, so they'll display inline and react to each other's widths | |
// Line-height and vertical align is used to ensure that the icons/text and things stay lined up. | |
// * Vertical align works in this case because inline-block elements are next to each other. | |
// * They vertically align with themselves and not the parent. | |
/* | |
The icons are font awesome icons | |
http://fortawesome.github.io/Font-Awesome/ | |
*/ | |
/* | |
The html structure goes like this | |
div.menu { | |
div.menu_item { | |
input.toggle { | |
.expander { | |
label { | |
i.menu_icon {} | |
span.menu_text {} | |
} | |
} | |
} | |
} | |
} | |
*/ | |
// How it all comes together | |
// | |
// 1.) By default the max-width of the expander is set to the icon size plus a little extra for padding. | |
// 2.) The expander overflow is set to hidden | |
// 3.) Fun fact. Labels work to toggle check boxes too. So we hide the check box itself. | |
// 4.) In the html we set the name of each radio button the same, so they interact with each other when clicked | |
// 5.) Give each radio a unique ID | |
// 6.) Using CSS, we then create a property that selects elements next to the input.toggle element | |
// When it is checked. | |
// 7.) Using this selector we set the max-width of the .expander and give it a transition property of all. For fun I added a background change as well. | |
// * Max-width will allow us to use a dynamic width to transition to with CSS. But it needs a maxiumum value. I set an arbitrary width of 16rem. | |
// If this is increased, the timing of the transition CSS property will need to be adjusted since it uses the max value to set the speed | |
// * That should get the boxes expanding and closing on click. | |
// 8.) To make it look like a menu. I wrapped each .menu_item with another div and gave it some background. | |
// 9.) There is also an issue of wrapping text. To make the button text not wrap apply the white-space: nowrap; property to the menu_item. | |
// 10.) From there, it's all just stylistic adjustments |
// Includes | |
@import url('https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css'); | |
// Variables | |
$icon_size: 3rem; // 32px @ 16px default rem size | |
$icon_color: #ccc; | |
$icon_color_hover: #fff; | |
$icon_color_checked: #ABDC38; | |
$max_expansion: 16rem; // 16*16 = 256px => max width of expansion, directly relates to the transition timing length | |
$menu_text_size: 1.5rem; // size of the menu text | |
$menu_text_color: #fff; | |
$menu_bg: #333; | |
$menu_item_padding: 1.5rem; | |
$menu_item_bg: none; | |
$menu_item_bg_hover: #000; | |
$menu_item_bg_checked: #222; | |
$menu_border_radius: $icon_size/4; | |
.menu { | |
font-family: arial; | |
background: $menu_bg; | |
//font-size: 0.0001rem; // fix for inline-block spacing "glitch" | |
//overflow: hidden; | |
display: table; | |
position: relative; | |
margin: 0 $menu_border_radius; | |
box-shadow: 0 $icon_size/1.5 $icon_size*3 rgba(0,0,0,0.8); | |
&:before, &:after { | |
content: ''; | |
position: absolute; | |
top: 0; | |
bottom: 0; | |
width: $menu_border_radius; | |
background: $menu_bg; | |
} | |
&:before { | |
left: -$menu_border_radius; | |
border-radius: $menu_border_radius 0 0 $menu_border_radius; | |
} | |
&:after { | |
right: -$menu_border_radius; | |
border-radius: 0 $menu_border_radius $menu_border_radius 0; | |
} | |
} | |
.menu_item { | |
display: block; | |
float: left; | |
white-space: nowrap; | |
color: $icon_color; | |
font-size: $menu_text_size; | |
//margin-right: 0.5rem; | |
&:last-child { | |
margin-right: 0; | |
} | |
.toggle { | |
display: none; | |
&:checked ~ { | |
& .expander { | |
max-width: $max_expansion; | |
background: $menu_item_bg_checked; | |
.menu_icon { | |
color: $icon_color_checked; | |
animation: none; | |
} | |
.menu_text { | |
color: $menu_text_color; | |
} | |
} | |
} | |
} | |
.expander { | |
max-width: $icon_size; | |
overflow: hidden; | |
transition: all ease-in-out 233ms; | |
padding: $menu_item_padding; | |
padding-right: $menu_item_padding; | |
&:hover { | |
background: $menu_item_bg_hover; | |
.menu_icon { | |
color: $icon_color_hover; | |
animation: jiggle ease-in-out 400ms infinite; | |
} | |
} | |
} | |
label { | |
line-height: $icon_size; | |
} | |
.menu_icon { | |
display: inline-block; | |
font-size: $icon_size; | |
line-height: $icon_size; | |
vertical-align: middle; | |
width: $icon_size; | |
text-align: center; | |
margin-right: 0.5rem; | |
transition: color ease-in-out 80ms; | |
} | |
.menu_text { | |
line-height: $icon_size; | |
color: transparent; | |
display: inline-block; | |
vertical-align: middle; | |
padding-right: $menu_item_padding; | |
transition: color ease-out 333ms; | |
} | |
} | |
.menu_title { | |
color: $menu_text_color; | |
font-size: $menu_text_size; | |
display: block; | |
float: left; | |
line-height: $icon_size; | |
padding: $menu_item_padding; | |
} | |
.positioner { | |
display: table; | |
margin: 0 auto; | |
margin-top: calc(50vh - #{$icon_size + $menu_item_padding/2}) | |
} | |
@keyframes jiggle { | |
0% { | |
transform: none; | |
} | |
25% { | |
transform: rotateZ(5deg);; | |
} | |
75% { | |
transform: rotateZ(-5deg) | |
} | |
100% { | |
transform: none; | |
} | |
} |