I'm trying to build a hamburger menu in the shape of...an actual hamburger.
My only small problem has to do with the "sesame seed" background image on the expanded menu. I managed to find a snippet that uses a radial gradient image When you click on the menu icon and the menu drops down, the white polka dot background image doesn't show up until after the transition is done.
The code I'm specifically looking at is the background-image line on the #menuList selector.
body {
margin: 0;
padding: 0;
font-family: 'Open Sans', sans-serif;
}
a {
text-decoration: none; /* no underlines */
}
#menuToggle {
display: block;
position: absolute;
height: 36px;
width: 36px;
top: 20px;
right: 20px;
z-index: 1;
color: #e5cb7a;
-webkit-user-select: none;
user-select: none; /* don't let 'em select text */
}
/* Style the "checkbox" used to activate the hamburger menu */
#menuToggle input {
display: block;
position: absolute;
height: 32px;
width: 32px;
top: -7px;
right: -7px;
cursor: pointer; /* make the burger pointy */
opacity: 0; /* hide the checkbox */
z-index: 2;
}
/* Make the menu look like a triangle shape by adding a thick border next to it. */
#menuToggle::before {
content: '';
position: absolute;
top: -10px;
right: -10px;
border-color: #e5cb7a; /* Bun-color */
border-style: solid;
border-width: 22px;
border-radius: 8px;
}
/* Style the three spans that make up the hamburger */
#menuToggle span {
display: block;
position: relative;
height: 4px;
width: 30px;
margin: 0px 0px 6px 9px;
border-radius: 3px;
z-index: 1;
transition: transform 0.5s,
opacity 0.55s ease;
}
/* Color the top span a lettuce color */
#topBun {
background: #32c704;
}
/* Color the middle span a burger color */
#meat {
background: #450101;
}
/* Color the bottom span a ketchup color */
#bottomBun {
background: #ec3521;
}
/* Move the top bun down 10px (its height), then turn it */
#menuToggle input:checked ~ #topBun {
background: #450101;
transform: translate(0px, 10px) rotate(45deg);
}
#menuToggle input:checked ~ #meat {
opacity: 0;
transform: rotate(0deg);
}
/* Move the bottom bun up 10px (its height), then turn it */
#menuToggle input:checked ~ #bottomBun {
background: #450101;
transform: translate(0px,-10px) rotate(-45deg);
}
#menuList {
display: inline-block;
position: absolute;
top: 0px;
right: 0px;
height: 100px;
width: 100px;
margin: -20px -20px 0 0;
padding: 50px 90px 0 0;
background: transparent;
list-style-type: none; /* no bullets, weapon-free zone */
/*-webkit-font-smoothing: antialiased;*/
/* Sesame seeds for the top bun of the expanded menu */
background-image: radial-gradient(white 20%, transparent 0);
background-size: 15px 12px;
background-position: 0 12px, 10px 10px;
/* Shrink the actual menu list until the hamburger is opened */
transform: translate(0px,-65px) scale(1,0.00001);
transition: transform 1.5s, background 1.5s;
}
/* Make a larger burger bun shape around the expanded hamburger menu */
#menuList::before {
content: '';
position: absolute;
top: 10px;
right: 10px;
border-style: solid;
border-width: 90px;
border-radius: 10px;
z-index: -1;
}
#menuList li {
padding: 3px 5px;
font-size: 22px;
text-align: center;
width: 170px;
color: #ffffff;
}
#menuList li:hover {
font-weight: bold;
letter-spacing: 2px;
}
/* Color the first menu option a lettuce color */
#about {
background: #32c704;
}
/* Color the second menu option a burger color */
#info {
background: #450101;
}
/* Color the third menu option a ketchup color */
#contact {
background: #ec3521;
}
/* Transform the list back to its normal "visible" size when the input is checked */
#menuToggle input:checked ~ ul {
transform: none;
}
<nav>
<div id="menuToggle">
<input type="checkbox" />
<span id="topBun"></span>
<span id="meat"></span>
<span id="bottomBun"></span>
<ul id="menuList">
<li id="about">ABOUT</li>
<li id="info">INFO</li>
<li id="contact">CONTACT</li>
</ul>
</div>
</nav>
I've slowed the transition down in this pen to better illustrate the problem.
How can I get the background to always show up instead of only when the menu is fully expanded?
CodePen
Your expanded menu “bun” was a border, not a background, and you had the background on the collapsed hamburger bun instead.
body {
margin: 0;
padding: 0;
font-family: 'Open Sans', sans-serif;
}
a {
text-decoration: none;
/* no underlines */
}
#menuToggle {
display: block;
position: absolute;
height: 36px;
width: 36px;
top: 20px;
right: 20px;
z-index: 1;
color: #e5cb7a;
-webkit-user-select: none;
user-select: none;
/* don't let 'em select text */
}
/* Style the "checkbox" used to activate the hamburger menu */
#menuToggle input {
display: block;
position: absolute;
height: 32px;
width: 32px;
top: -7px;
right: -7px;
cursor: pointer;
/* make the burger pointy */
opacity: 0;
/* hide the checkbox */
z-index: 2;
}
/* Make the menu look like a triangle shape by adding a thick border next to it. */
#menuToggle::before {
content: '';
position: absolute;
top: -10px;
right: -10px;
border-color: #e5cb7a;
/* Bun-color */
border-style: solid;
border-width: 22px;
border-radius: 8px;
}
/* Style the three spans that make up the hamburger */
#menuToggle span {
display: block;
position: relative;
height: 4px;
width: 30px;
margin: 0px 0px 6px 9px;
border-radius: 3px;
z-index: 1;
transition: transform 0.5s, opacity 0.55s ease;
}
/* Color the top span a lettuce color */
#topBun {
background: #32c704;
}
/* Color the middle span a burger color */
#meat {
background: #450101;
}
/* Color the bottom span a ketchup color */
#bottomBun {
background: #ec3521;
}
/* Move the top bun down 10px (its height), then turn it */
#menuToggle input:checked~#topBun {
background: #450101;
transform: translate(0px, 10px) rotate(45deg);
}
#menuToggle input:checked~#meat {
opacity: 0;
transform: rotate(0deg);
}
/* Move the bottom bun up 10px (its height), then turn it */
#menuToggle input:checked~#bottomBun {
background: #450101;
transform: translate(0px, -10px) rotate(-45deg);
}
#menuList {
display: inline-block;
position: absolute;
top: 0px;
right: 0px;
height: 100px;
width: 100px;
margin: -20px -20px 0 0;
padding: 50px 90px 0 0;
background: transparent;
list-style-type: none;
/* no bullets, weapon-free zone */
/*-webkit-font-smoothing: antialiased;*/
/* Shrink the actual menu list until the hamburger is opened */
transform: translate(0px, -65px) scale(1, 0.00001);
transition: transform 1.5s;
}
/* Make a larger burger bun shape around the expanded hamburger menu */
#menuList::before {
content: '';
position: absolute;
top: 10px;
right: 10px;
bottom: -30px;
left: 0;
border-radius: 10px;
z-index: -1;
/* Sesame seeds for the top bun of the expanded menu */
background-color: #e5cb7a;
background-image: radial-gradient(white 20%, transparent 0);
background-size: 15px 12px;
background-position: 0 12px, 10px 10px;
}
#menuList li {
padding: 3px 5px;
font-size: 22px;
text-align: center;
width: 170px;
color: #ffffff;
}
#menuList li:hover {
font-weight: bold;
letter-spacing: 2px;
}
/* Color the first menu option a lettuce color */
#about {
background: #32c704;
}
/* Color the second menu option a burger color */
#info {
background: #450101;
}
/* Color the third menu option a ketchup color */
#contact {
background: #ec3521;
}
/* Transform the list back to its normal "visible" size when the input is checked */
#menuToggle input:checked~ul {
transform: translate3d(0,0,0);
}
<nav>
<div id="menuToggle">
<input type="checkbox" />
<span id="topBun"></span>
<span id="meat"></span>
<span id="bottomBun"></span>
<ul id="menuList">
<a href="#">
<li id="about">ABOUT</li>
</a>
<a href="#">
<li id="info">INFO</li>
</a>
<a href="#">
<li id="contact">CONTACT</li>
</a>
</ul>
</div>
</nav>
Related
I want to draw a line below a link and apply animation on it, so I use pseudo element. It produces the line as expected, but if there is a large padding around the link, the line appears far away. Is there a way to ignore the padding and draw the line right below text?
a {
position: absolute;
padding: 20px 0;
top: 50%;
left: 50%;
margin-top: -30px;
margin-left: -30px;
line-height: 20px;
}
a:after {
position: absolute;
bottom: 0;
left: 0;
width: 0;
content: '';
transition: width .3s;
display: block;
}
a:hover:after {
width: 100%;
border-top: 1px solid #333;
}
<a>Link Text</a>
You can just remove the absolute position since the pseudo is set on :after so that it's placed right after the text.
a {
position: absolute;
padding: 20px 0;
top: 50%;
left: 50%;
margin-top: -30px;
margin-left: -30px;
line-height: 20px;
border: 1px solid aqua;
}
a:after {
content: "";
display: block;
border-top: 1px solid #333;
width: 0;
transition: width .3s;
}
a:hover:after {
width: 100%;
}
<a>Link Text</a>
Side note, you might encounter the double tap behavior for the kind of hover effects on touch devices such as phones, tablets. Add this to fix that:
#media (hover: none) {
a:hover:after {
display: none;
}
}
In addition, the effects can also be done with linear-gradient(), example:
a {
display: inline-block;
text-decoration: none;
border: 1px solid aqua;
font-size: 16px;
padding: 20px 0;
background-image: linear-gradient(to bottom, blue, blue);
background-position: 0 38px; /*adjust this based on font-size and padding*/
background-size: 0 1px;
background-repeat: no-repeat;
transition: background-size .3s;
}
a:hover {
background-size: 100% 1px;
}
Link text
I have been looking for a slide in the menu for mobile in bootstrap, the closest that I could get is this one https://codepen.io/erikterwan/pen/EVzeRP , But I can't make it open from right to left and have the hamburger in the bottom right, any ideas?.
This will be little tricky because the creator writes:
Too bad the menu has to be inside of the button
but hey, it's pure CSS magic.
The code to add is
/*
* This move all the navbar to right because the ul is inside the button
*/
#menuToggle{
position:fixed;
left: calc(100vw - 70px);
top:calc(100vh - 50px);
}
/*
* This will position the menu
*/
#menu{
top: calc(-100vh + 50px);
left: 70px;
margin: 0;
margin-top: -100px;
height: 100vh;
}
/*
* Fade menu from the right
*/
#menuToggle input:checked ~ ul
{
transform: translate(-100%, 0);
opacity: 1;
}
/*
* Correct the overflow
*/
html{
max-width: 100vw;
overflow-x: hidden;
}
/*
* Made by Erik Terwan
* 24th of November 2015
* All rights reserved
*
* Modified by Alessandro Lodi
* 5th of August 2017
*
* If you are thinking of using this in
* production code, beware of the browser
* prefixes.
*/
body
{
margin: 0;
padding: 0;
/* make it look decent enough */
background: #232323;
color: #cdcdcd;
font-family: "Avenir Next", "Avenir", sans-serif;
}
a
{
text-decoration: none;
color: #232323;
transition: color 0.3s ease;
}
a:hover
{
color: tomato;
}
#menuToggle
{
display: block;
position: relative;
top: 50px;
left: 50px;
z-index: 1;
-webkit-user-select: none;
user-select: none;
}
#menuToggle input
{
display: block;
width: 40px;
height: 32px;
position: absolute;
top: -7px;
left: -5px;
cursor: pointer;
opacity: 0; /* hide this */
z-index: 2; /* and place it over the hamburger */
-webkit-touch-callout: none;
}
/*
* Just a quick hamburger
*/
#menuToggle span
{
display: block;
width: 33px;
height: 4px;
margin-bottom: 5px;
position: relative;
background: #cdcdcd;
border-radius: 3px;
z-index: 1;
transform-origin: 4px 0px;
transition: transform 0.5s cubic-bezier(0.77,0.2,0.05,1.0),
background 0.5s cubic-bezier(0.77,0.2,0.05,1.0),
opacity 0.55s ease;
}
#menuToggle span:first-child
{
transform-origin: 0% 0%;
}
#menuToggle span:nth-last-child(2)
{
transform-origin: 0% 100%;
}
/*
* Transform all the slices of hamburger
* into a crossmark.
*/
#menuToggle input:checked ~ span
{
opacity: 1;
transform: rotate(45deg) translate(-2px, -1px);
background: #232323;
}
/*
* But let's hide the middle one.
*/
#menuToggle input:checked ~ span:nth-last-child(3)
{
opacity: 0;
transform: rotate(0deg) scale(0.2, 0.2);
}
/*
* Ohyeah and the last one should go the other direction
*/
#menuToggle input:checked ~ span:nth-last-child(2)
{
opacity: 1;
transform: rotate(-45deg) translate(0, -1px);
}
/*
* Make this absolute positioned
* at the top left of the screen
*/
#menu
{
position: absolute;
width: 250px;
margin: -100px 0 0 -50px;
padding: 50px;
padding-top: 125px;
background: #ededed;
list-style-type: none;
-webkit-font-smoothing: antialiased;
/* to stop flickering of text in safari */
transform-origin: 0% 0%;
//transform: translate(-100%, 0);
transition: transform 0.5s cubic-bezier(0.77,0.2,0.05,1.0);
}
#menu li
{
padding: 10px 0;
font-size: 22px;
}
/*
* And let's fade it in from the left
*/
#menuToggle input:checked ~ ul
{
transform: translate(-100%, 0);
opacity: 1;
}
#menuToggle{
position:fixed;
left: calc(100vw - 70px);
top:calc(100vh - 50px);
}
#menu{
top: calc(-100vh + 50px);
left: 70px;
margin: 0;
margin-top: -100px;
height: 100vh;
}
html{
max-width: 100vw;
overflow-x: hidden;
}
<nav role="navigation">
<div id="menuToggle">
<!--
A fake / hidden checkbox is used as click reciever,
so you can use the :checked selector on it.
-->
<input type="checkbox" />
<!--
Some spans to act as a hamburger.
They are acting like a real hamburger,
not that McDonalds stuff.
-->
<span></span>
<span></span>
<span></span>
<!--
Too bad the menu has to be inside of the button
but hey, it's pure CSS magic.
-->
<ul id="menu">
<li>Home</li>
<li>About</li>
<li>Info</li>
<li>Contact</li>
<li>Show me more</li>
</ul>
</div>
</nav>
I'm working on a menu with a sliding underline with target, I am really close but I can't figure to make it responsive. The "underline" doesn't stick at the center of the link when resizing the window.
Here is a JSFiddle
nav {
margin-top:30px;
font-size: 15pt;
background: #FFF;
position: relative;
width: 100%;
height:50px;
}
nav a {
text-align:center;
background: #FFF;
display: block;
float: left;
padding: 2% 0;
width: 33.33%;
text-decoration: none;
transition: .4s;
color: red;
}
.effect {
position: absolute;
left: 22.5%;
transition: 0.4s ease-in-out;
}
nav a:nth-child(1):target ~ .effect {
left: 22.5%;
/* the middle of the first <a> */
}
nav a:nth-child(2):target~ .effect {
left: 56%;
/* the middle of the second <a> */
}
nav a:nth-child(3):target ~ .effect {
left: 90%;
/* the middle of the third <a> */
}
.ph-line-nav .effect {
width: 34px;
height: 2px;
bottom: 5px;
background: blue;
margin-left:-50px;
}
Each element is 33.33% wide. Divide that in half, that's 16.66%, so that will be the center of the element. Using 16.66% as the default left value will put the left edge of .effect in the center of the first element. To center the .effect in the true center, move it back 50% of it's own with with translateX().
So the first element's left should be 16.66%.
The second element will be 49.99% (99.99 / 2)
The third element will be 83.33% (99.99 - 16.6 or 66.66 + 16.66)
nav {
margin-top:30px;
font-size: 15pt;
background: #FFF;
position: relative;
height:50px;
display: flex;
}
nav a {
text-align:center;
background: #FFF;
display: block;
padding: 2% 0;
flex-basis: 33.33%;
text-decoration: none;
transition: .4s;
color: red;
}
.effect {
position: absolute;
left: 16.66%;
transition: 0.4s ease-in-out;
transform: translateX(-50%);
}
nav a:nth-child(1):target ~ .effect {
left: 16.66%;
/* the middle of the first <a> */
}
nav a:nth-child(2):target~ .effect {
left: 49.99%;
/* the middle of the second <a> */
}
nav a:nth-child(3):target ~ .effect {
left: 83.33%;
/* the middle of the third <a> */
}
.ph-line-nav .effect {
width: 34px;
height: 2px;
bottom: 5px;
background: blue;
}
<nav class="ph-line-nav">
AA
AA
AA
<div class="effect"></div>
</nav>
I have a nav element that on mouse hover reveal my menu, it works fine on Safari and Chrome however not in Firefox nor in IE:
/* start nav menu morph */
nav {
width: 23%;
background: #222222;
color: rgba(255, 255, 255, 0.87);
-webkit-clip-path: circle(16px at 30px 24px);
clip-path: circle(16px at 30px 24px);
-webkit-transition: -webkit-clip-path 0.5625s, clip-path 0.375s;
transition: -webkit-clip-path 0.5625s, clip-path 0.375s;
}
nav:hover {
-webkit-transition-timing-function: ease-out;
transition-timing-function: ease-out;
-webkit-transition-duration: 0.75s;
transition-duration: 0.75s;
-webkit-clip-path: circle(500px at 225px 24px);
clip-path: circle(500px at 225px 24px);
}
nav a {
width: 100%;
display: block;
line-height: 50px;
padding: 0 20px;
color: inherit;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
nav a:hover {
background: #ffe082;
}
nav a:active {
background: #ffca28;
}
.nav-sim {
position: absolute;
right: 0;
top: -6px;
}
.navicon {
padding: 23px 20px;
cursor: pointer;
-webkit-transform-origin: 32px 24px;
-ms-transform-origin: 32px 24px;
transform-origin: 32px 24px;
}
.navicon div {
position: relative;
width: 20px;
height: 2px;
background: rgb(254, 70, 70);
}
.navicon div:before,
.navicon div:after {
display: block;
content: "";
width: 20px;
height: 2px;
background: rgb(254, 70, 70);
position: absolute;
}
.navicon div:before {
top: -7px;
}
.navicon div:after {
top: 7px;
}
.fa-sim {
font-size: large;
margin-left: 5px;
}
/* end nav menu morph */
<noscript>
<style>
#navmenusim {
display: none;
}
</style>
</noscript>
<nav class="nav-sim" id="navmenusim">
<div class="navicon">
<div></div>
</div>
Home<i class="fa fa-home icon i-sim fa-sim"></i>
Blog<i class="fa fa-rss icon i-sim fa-sim"></i>
Contact<i class="fa fa-mail icon i-sim fa-sim"></i>
</nav>
The menu in Firefox and IE is always visible, the clip-path doesn't work. How to fix it?
As mentioned in my comment to the question, CSS clip-path won't work in Firefox. You would need to use SVG along with url() syntax for Firefox support. IE (even 11 and Edge) supports neither the CSS or SVG version of clip-path. You can check browser compatibility chart at Can I Use.
You can make use of the max-width, max-height, border-radius and overflow properties to sort of get a similar output to what you need. Below is a sample snippet which should work in all browsers.
/* start nav menu morph */
nav {
margin-top: 10px;
width: 23%;
background: #222222;
color: rgba(255, 255, 255, 0.87);
max-height: 50px;
max-width: 50px;
border-radius: 50%;
overflow: hidden;
transition: max-height .375s, max-width .375s, border-radius .125s .25s;
}
nav:hover {
max-height: 500px;
max-width: 500px;
border-radius: 0%;
transition: max-height .75s ease-out, max-width .75s ease-out, border-radius .75s ease-out;
}
nav a {
width: 100%;
display: block;
line-height: 50px;
padding: 0 20px;
color: inherit;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
nav a:hover {
background: #ffe082;
}
nav a:active {
background: #ffca28;
}
.nav-sim {
position: absolute;
right: 0;
top: -6px;
}
.navicon {
padding: 23px 20px;
cursor: pointer;
-webkit-transform-origin: 32px 24px;
-ms-transform-origin: 32px 24px;
transform-origin: 32px 24px;
}
.navicon div {
position: relative;
margin-left: -5px;
width: 20px;
height: 2px;
background: rgb(254, 70, 70);
}
.navicon div:before,
.navicon div:after {
display: block;
content: "";
width: 20px;
height: 2px;
background: rgb(254, 70, 70);
position: absolute;
}
.navicon div:before {
top: -7px;
}
.navicon div:after {
top: 7px;
}
.fa-sim {
font-size: large;
margin-left: 5px;
}
/* end nav menu morph */
<nav class="nav-sim" id="navmenusim">
<div class="navicon">
<div></div>
</div>
Home<i class="fa fa-home icon i-sim fa-sim"></i>
Blog<i class="fa fa-rss icon i-sim fa-sim"></i>
Contact<i class="fa fa-mail icon i-sim fa-sim"></i>
</nav>
I have created a slant style triangle using borders to use on navigation items, however the border that is used to define the length of the slant is fixed and it needs to adapt based on the content inside the list item. I also want to use the same css class for each list item.
Is this the best solution for what I am trying to achieve or is there an alternative method that has the same result?
I am open to JS solutions too.
I have used the following CSS so far:
li {
float: left;
position: relative;
height: 20px;
background: #a1a8ad;
padding: 5px 12px;
margin-right: 10px;
list-style: none;
}
li:before {
content: "";
position: absolute;
top: -3px;
width: 0;
height: 1px;
left: 0px;
border-right: 63px solid #a1a8ad; /* razorblade color */
border-top: 2px solid rgba(0, 0, 0, 0); /* transparent */
}
JSFiddle here
You can't use percentages for the border-width but you can use a rotated pseudo element to make the slanted top border :
li {
float: left;
position: relative;
margin-right: 10px;
list-style: none;
overflow: hidden;
padding-top: 8px;
}
li a {
display: block;
background: #a1a8ad;
padding: 5px 12px;
color: #000;
height: 20px;
text-decoration: none;
}
li:before {
content: "";
position: absolute;
top: 0;
right: 0;
width: 150%;
height: 30px;
background: #a1a8ad; /* razorblade color */
-webkit-transform-origin: 100% 0;
-ms-transform-origin: 100% 0;
transform-origin: 100% 0;
-webkit-transform: rotate(-2deg);
-ms-transform: rotate(-2deg);
transform: rotate(-2deg);
z-index: -1;
}
<nav>
<ul>
<li>Home
</li>
<li>About Us
</li>
</ul>
</nav>