Skip to content

Instantly share code, notes, and snippets.

@iamarya2k24
Created March 15, 2020 02:31
Show Gist options
  • Save iamarya2k24/a90b6f6e1d0022976992af6b76147638 to your computer and use it in GitHub Desktop.
Save iamarya2k24/a90b6f6e1d0022976992af6b76147638 to your computer and use it in GitHub Desktop.
Content aware dropdown

Content aware dropdown

Stripe.com style dropdown, that measures the dropdown content size, and makes a backdrop follower accordingly.

A Pen by Rune Sejer Hoffmann on CodePen.

License.

.content
nav.navigation
div.navigation__backdrop
div.navigation__container
ul.navigation__list
li.navigation__item Home
.navigation__item-content
span.fontelico-emo-coffee
p This menu is aware of it's own content
p ... Kinda the JS measures the content and
p makes a backdrop accordingly
li.navigation__item Portfolio
.navigation__item-content
span.fontelico-emo-thumbsup
p Have you ever visited stripe.com?
p There you can see same type, just full fledged
li.navigation__item Services
.navigation__item-content
span.fontelico-emo-beer
p Just pop your content into this menu, and let the JS handle the rest.
p Feel free to use it on your own project
p Have a look at my other pens
a(class='navigation__item-button' href='https://codepen.io/RSH87/' target='_blank') here
.content__main
h2.content__main-headline Content aware dropdown
h6.content__main-signoff By RSH87
class sizeable_dropdown {
constructor(){
this.x;
this.nav_items = document.querySelectorAll('.navigation__item');
this.backdrop = document.querySelector('.navigation__backdrop');
this.nav_items.forEach(trigger => trigger.addEventListener('mouseenter', cn => this.handle_enter(cn)));
this.nav_items.forEach(trigger => trigger.addEventListener('mouseleave', cn => this.handle_leave(cn)));
}
handle_enter(e) {
e.target.classList.add('navigation__item-enter');
setTimeout(() => e.target.classList.add('navigation__item-active'),100);
let item_content = e.target.querySelector(".navigation__item-content");
let w = item_content.offsetWidth;
let h = item_content.offsetHeight;
this.x = e.target.offsetLeft + e.target.offsetWidth / 2 - w / 2;
this.handle_backdrop(w, h);
}
handle_backdrop(w, h) {
setTimeout(() => this.backdrop.classList.add('navigation__backdrop_active'),100);
Object.assign(this.backdrop.style, {
transform : "translateX(" + this.x +"px)",
height : h + "px",
width : w + "px"
});
}
handle_leave(e) {
e.target.classList.remove('navigation__item-enter', 'navigation__item-active');
setTimeout(() => this.backdrop.classList.remove('navigation__backdrop_active'),100);
}
}
new sizeable_dropdown();
@import url(http://weloveiconfonts.com/api/?family=fontelico);
//Setup
$font-color-primary: #ffffff;
$font-color-secondary: rgba(0, 0, 0, 0.6);
$color-primary: #1f0743;
$color-secondary: #58E1E9;
$t: .3s cubic-bezier(0.22, 0.61, 0.36, 1);
[class*="fontelico-"]:before {
font-family: 'fontelico', sans-serif;
color: $color-secondary;
font-size: 28px;
opacity: .8;
}
@mixin triangle($color) {
&:before{
content: '';
position: absolute;
top: -8px;
left: 0;
right: 0;
margin: auto;
background: $color;
height: 20px;
width: 20px;
border-radius: 3px;
transform: rotate(45deg);
}
}
*{
-webkit-font-smoothing: antialiased !important;
text-shadow: 1px 1px 1px rgba(0,0,0,0.004);
}
body{
background-color: $color-primary;
background-image: url("data:image/svg+xml,%3Csvg width='250' height='150' viewBox='0 0 52 26' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%237352a7' fill-opacity='0.10'%3E%3Cpath d='M10 10c0-2.21-1.79-4-4-4-3.314 0-6-2.686-6-6h2c0 2.21 1.79 4 4 4 3.314 0 6 2.686 6 6 0 2.21 1.79 4 4 4 3.314 0 6 2.686 6 6 0 2.21 1.79 4 4 4v2c-3.314 0-6-2.686-6-6 0-2.21-1.79-4-4-4-3.314 0-6-2.686-6-6zm25.464-1.95l8.486 8.486-1.414 1.414-8.486-8.486 1.414-1.414z' /%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
font-family: 'Nunito', sans-serif;
height: 100vh;
display: flex;
box-sizing: border-box;
overflow: hidden;
}
.content{
max-width: 1070px;
margin-left: auto;
margin-right: auto;
}
//Nav must have starts here
.navigation{
height: 70px;
&__backdrop{
background: #f8f8f8;
position: absolute;
top: 90px;
left: 0;
right: 0;
opacity: 0;
border-radius: 3px;
z-index: 0;
@include triangle(#f8f8f8);
}
&__backdrop_active{
opacity: 1;
transition: all $t, opacity $t;
}
&__container{
max-width: 1040px;
margin-left: auto;
margin-right: auto;
}
&__list{
display: flex;
justify-content: center;
align-items: center;
}
&__item{
position: relative;
list-style: none;
padding: 40px;
display: flex;
justify-content: center;
cursor: pointer;
font-weight: 200;
font-size: 20px;
color: $font-color-primary;
}
&__item-content{
position: absolute;
padding: 40px;
font-size: 14px;
top: 80px;
left: 50%;
color: $font-color-secondary;
transform:translateX(-50%);
text-align: center;
opacity: 0;
transition: opacity $t;
display: none;
}
&__item-button{
padding: 12px 35px 12px 35px;
margin-top: 15px;
display: inline-block;
border-radius: 50px;
background: $color-secondary;
color: #fff;
text-decoration: none;
}
&__item-enter{
.navigation__item-content{
display: block;
}
}
&__item-active{
.navigation__item-content{
opacity: 1;
}
}
}
//Just prettyfying things here
.content{
flex-grow: 1;
display: flex;
flex-direction: column;
&__main{
display: flex;
flex-direction: column;
flex-grow: 1;
align-items: center;
justify-content: center;
}
&__main-headline{
font-size: calc(2vw + 26px);
color: $color-secondary;
align-self: center;
font-weight: bold;
}
&__main-signoff{
margin-top: 10px;
font-size: 12px;
color: $font-color-primary;
}
}
//Faking some content here
p{
min-width: 150px;
margin-top: 10px;
white-space: nowrap;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment