I have a simple submenu that is toggled into visibility using the :focus CSS selector.
It shows the submenu by turning the submenu from display: none to display: block with the following CSS:
.menu-item:focus > .submenu {
display: block;
}
This all works, and if I click on a different menu item (or anywhere else on the page) the submenu then disappears.
Is it possible however with CSS (and I'm guessing :focus) to have it so when I click on the initial menu-item again (i.e. for a 2nd time) it also toggles away? At the moment this isn't happening - it is only happening when I click anywhere else (which is clearly when the element loses focus).
Many thanks
Codepen: https://codepen.io/emilychews/pen/RwVVmjm
body {
display: flex;
justify-content: center;
margin: 0;
height: 100vh;
width: 100%;
}
header {
margin-top: 2rem;
display: flex;
width: 50%;
justify-content: space-evenly;
align-items: center;
padding: 1rem;
background: red;
height: 2rem;
}
.menu-item {
position: relative;
padding: 1rem;
background: yellow;
cursor: pointer;
}
/* select the focused menu-item's child elements (the submenu) */
.menu-item:focus > .submenu {
display: block;
}
.submenu {
display: none; /* changes to 'block' with focus */
padding: 1rem;
background: lightblue;
position: absolute;
top: 4rem;
left: 0;
width: 6rem;
}
<header>
<div id="item-1" class="menu-item menu-item-1" tabindex="0">ITEM 1
<div id="sub-item-1" class="submenu submenu-1">SUB-ITEM-1</div>
</div>
<div id="item-2" class="menu-item menu-item-2" tabindex="0">ITEM 2
<div id="sub-item-2" class="submenu submenu-2">SUB-ITEM-2</div>
</div>
</header>
The best way for my opinion is to use JavaScript.
However you can use checkbox and changing the wrapper div to label for only CSS solution :
body {
display: flex;
justify-content: center;
margin: 0;
height: 100vh;
width: 100%;
}
header {
margin-top: 2rem;
display: flex;
width: 50%;
justify-content: space-evenly;
align-items: center;
padding: 1rem;
background: red;
height: 2rem;
}
.menu-item {
position: relative;
padding: 1rem;
background: yellow;
cursor: pointer;
}
/* select the element after the checked checkbox (the submenu) */
.dis:checked ~ .submenu {
display: block;
}
.dis{ /*reset default checkbox style*/
display: none
}
.submenu {
display: none; /* changes to 'block' with focus */
padding: 1rem;
background: lightblue;
position: absolute;
top: 4rem;
left: 0;
width: 6rem;
}
<header>
<label id="item-1" class="menu-item menu-item-1" tabindex="0">ITEM 1
<input type="checkbox" class="dis">
<div id="sub-item-1" class="submenu submenu-1">SUB-ITEM-1</div>
</label>
<label id="item-2" class="menu-item menu-item-2" tabindex="0">ITEM 2
<input type="checkbox" class="dis">
<div id="sub-item-2" class="submenu submenu-2">SUB-ITEM-2</div>
</label>
</header>
Related
I have a navigation bar and I added a red line on the bottom when hovering any item of the list, but I want to move that red line under the header (something like "Services"), any idea how to achieve this?
I added an small sample in codepen so you can easily check the HTML and CSS code
header {
background-color: lightblue;
padding-top: 1rem;
position: sticky;
top: 0;
display: flex;
align-items: center;
justify-content: space-around;
}
header nav {
min-width: 50%;
}
header nav ul {
margin: 0;
height: 100%;
list-style: none;
padding-left: 0;
display: flex;
align-items: center;
justify-content: space-between;
}
header li:hover {
height: 100%;
border-bottom: 2px solid red;
}
<header>
<a href="/">
<p>Whatever logo</p>
</a>
<nav>
<ul>
<li>About us</li>
<li>Services</li>
<li>Pricing</li>
<li>Blog</li>
</ul>
</nav>
CONTACT
</header>
Link to check the code
You can fix the header height and also fix the height of navbar items.
Also, you had one issue where on hover li elements are moving. You can also fix that with always adding border with transparent color to the element, so the overall height of the element won't change on hover state.
Here is the fixed CSS
header {
background-color: lightblue;
position: sticky;
display: flex;
height: 60px;
align-items: center;
justify-content: space-around;
}
header nav {
min-width: 50%;
}
header nav ul {
margin: 0;
height: 100%;
list-style: none;
padding-left: 0;
display: flex;
align-items: center;
justify-content: space-between;
height: 60px;
}
header li {
display: flex;
align-items: center;
border-bottom: 2px solid transparent;
height: 60px;
}
header li:hover {
border-bottom: 2px solid red;
}
https://codepen.io/swarajgk/pen/JjZewPo?editors=1100
I think just giving height to all list elements the same as the header will work.
Like this:-
header {
background-color: lightblue;
padding-top: 1rem;
height: 3rem;
position: sticky;
top: 0;
display: flex;
align-items: center;
justify-content: space-around;
}
header nav {
min-width: 50%;
height : 100%;
}
header nav ul {
margin: 0;
height: 100%;
list-style: none;
padding-left: 0;
display: flex;
align-items: center;
justify-content: space-between;
}
header li{
height: inherit;
}
header li:hover {
border-bottom: 2px solid red;
}
<body>
<header>
<a href="/"
><p>Whatever logo</p></a>
<nav>
<ul>
<li>About us</li>
<li>Services</li>
<li>Pricing</li>
<li>Blog</li>
</ul>
</nav>
CONTACT
</header>
</body>
Hope this solves the issue.
header {
background-color: lightblue;
padding-top: 1rem;
height: 3rem;
position: sticky;
top: 0;
display: flex;
align-items: center;
justify-content: space-around;
}
header nav {
min-width: 50%;
height : 100%;
}
header nav ul {
margin: 0;
height: 100%;
list-style: none;
padding-left: 0;
display: flex;
align-items: center;
justify-content: space-between;
}
header li{
height: inherit;
}
header li:hover {
border-bottom: 2px solid red;
}
I'd suggest the following approach, with explanatory comments in the CSS:
/* removing default padding and margin from all
elements, and forcing the browser to use the
same sizing algorithm - border-box - to calculate
element sizes, including the padding and border
widths in the declared size: */
*, ::before, ::after {
box-sizing: border-box;
padding: 0;
margin: 0;
}
/* setting common properties for the two element
groups: */
header,
header nav ul {
/* using display: flex layout: */
display: flex;
/* forcing the flex-items within the flex parent
to take the full height of that parent: */
align-items: stretch;
}
header {
background-color: lightblue;
block-size: 3em;
position: sticky;
justify-content: space-around;
}
/* using :is() to combine the two selectors
header a,
header li
into one selector: */
header :is(a, li) {
/* using grid layout: */
display: grid;
/* positioning the - including text - content
at the center of the element: */
place-items: center;
}
header nav {
min-width: 50%;
}
header nav ul {
/* the <ul> isn't a flex-item so we have to specify
that we want it to take all available space on
the block-axis (equivalent to 'height' in left-to-right
languages such as English): */
block-size: 100%;
list-style: none;
justify-content: space-between;
}
header li {
/* to prevent the jumping content: */
border-bottom: 2px solid transparent;
}
header li:hover {
/* to style the color of the bottom border: */
border-bottom-color: red;
}
<header>
<a href="/">
<p>Whatever logo</p>
</a>
<nav>
<ul>
<li>About us</li>
<li>Services</li>
<li>Pricing</li>
<li>Blog</li>
</ul>
</nav>
CONTACT
</header>
JS Fiddle demo.
References:
align-items.
display.
justify-content.
place-items.
Bibliography:
"Aligning items in a flex container," MDN.
"Basic concepts of flexbox," MDN.
"Box alignment in grid layout," MDN.
Hamburger Menu
As shown above, my hamburger menu is stuck in the top left of its container. I'm trying to get it centered with the rest of the header content. Right now this is the code I have...
HTML
<header>
<ul class="main-menu-ls">
<li class="main-menu-ls main-logo">
<a class="logo-link" href="artsol.HTML"></a>
</li>
<li class="main-menu-ls search-wrapper">
<form class="main-search" action="/search">
<input class="main-search-bar-input" type="search" name="q" placeholder="Search:" value=""
autocapitalize="off" autocomplete="off">
</form>
</li>
<li class="main-menu-ls cart-link-container">
<a class="cart-link" href="cart.html"></a>
</li>
<li class="main-menu-ls wallet-btn-container">
<button onclick="togglePopupWallet()" class="wallet-btn">Wallet</button>
</li>
<li class="main-menu-ls login-btn-container">
<button onclick="togglePopupLogin()" class="login-btn">Login</button>
</li>
<li class="h-menu-container" id="h-menu-container">
<input class="main-menu-ls menu-checkbox" type="checkbox" id="menu_checkbox">
<label class="h-menu-btn" for="menu_checkbox">
<div></div>
<div></div>
<div></div>
</label>
</li>
</ul>
CSS
.main-menu-ls {
height: 48px;
margin: 0;
padding: 0;
width: 100%;
border: 0;
border-bottom: 1px solid #443E7A;
display: inline-flex;
text-align: center;
align-items: center;
justify-content: center;
list-style: none;
}
.h-menu-container {
margin: 0 auto;
position: relative;
text-align: center;
display: inline-flex;
width: var(--main-menu-height);
height: var(--main-menu-height);
align-items: center;
}
.h-menu-btn {
justify-content: center;
align-items: center;
text-align: center;
}
#menu_checkbox {
display: none;
}
label {
display: inline-block;
position: relative;
align-items: center;
justify-content: center;
/* top: 75%; */
/* right: 0;
left: 0; */
margin: 0 auto;
width: var(--main-menu-height);
height: var(--main-menu-height);
/* transform: translateY(-50%); */
transition: 0.3s ease transform, 0.3s
ease background-color;
cursor: pointer;
}
What I want to happen is to have the hamburger menu toggle centered in the container and when I toggle it'll do a little animation where it turns into a horizontal ellipse in the same position while changing the parent containers background color to match the menu that will be added. Although I can't continue until I find out how to center the divs that create the menu.
There are three ways to center a child in a div(parent).
/* Using FlexBox */
.parent {
display: flex;
align-items: center;
justify-content: center;
width: 100px;
height: 100px;
background-color: aqua;
}
/* Using Grid Layout */
.parent2 {
display: grid;
place-content: center;
width: 100px;
height: 100px;
background-color: rgb(112, 172, 132);
}
/* Giving the parent position relative and making the child postion absoulute */
.parent3 {
position: relative;
width: 100px;
height: 100px;
background-color: rgb(88, 20, 165);
}
.parent3 h1 {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -100%);
}
<div class="parent">
<h1>ABC</h1>
</div>
<div class="parent2">
<h1>ABC</h1>
</div>
<div class="parent3">
<h1>ABC</h1>
</div>
I have this navigation bar that works really well. It is fixed so it follows you as you scroll through the website. However, I would like for the navbar to only start in the second section (#home) and for it to not be visible in the first section (#section0).
Could I please have some help?
#section0 {
width: 100%;
height: 100vh;
background-color: blue;
}
#home {
width: 100%;
height: 100vh;
background-color: white;
display: block;
margin: 0 auto;
}
#home ul {
display: grid;
grid-template-columns: 1fr auto 1fr;
align-items: center;
z-index: 9999;
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: black;
position: -webkit-fixed;
/* Safari */
position: fixed;
top: 0;
}
#home ul li.left-menu {
display: flex;
justify-content: flex-end;
}
#home ul li.right-menu {
display: flex;
justify-content: flex-start;
}
#home li a {
display: block;
color: white;
text-align: center;
padding: 13px 20px;
text-decoration: none;
font-family: Futura;
font-size: 8px;
}
#home li a:hover {
color: #00CFFF;
}
#home .active {
color: #00CFFF;
}
#secondpage {
height: 100vh;
width: 100%;
background-color: orange;
}
<section id="section0">
</section>
<section id="home">
<ul>
<li class="left-menu">
<a class="active" href="#home">HOME</a>
HOW IT WORKS
WHY CHOOSE US
</li>
</li>
<li class="right-menu">
SERVICES
OUR GALLERY
CONTACT US
</li>
</section>
<section id="secondpage">
</section>
Just set a higher z-index for the first section.
body {
margin: 0;
padding: 0;
}
#section0 {
width: 100%;
height: 100vh;
background-color: blue;
z-index: 99999;
position: relative;
}
#home {
width: 100%;
height: 100vh;
background-color: white;
display: block;
margin: 0 auto;
}
#home ul {
display: grid;
grid-template-columns: 1fr auto 1fr;
align-items: center;
z-index: 9999;
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: black;
position: -webkit-fixed;
/* Safari */
position: fixed;
top: 0;
}
#home ul li.left-menu {
display: flex;
justify-content: flex-end;
}
#home ul li.right-menu {
display: flex;
justify-content: flex-start;
}
#home li a {
display: block;
color: white;
text-align: center;
padding: 13px 20px;
text-decoration: none;
font-family: Futura;
font-size: 8px;
}
#home li a:hover {
color: #00CFFF;
}
#home .active {
color: #00CFFF;
}
#secondpage {
height: 100vh;
width: 100%;
background-color: orange;
}
<section id="section0">
</section>
<section id="home">
<ul>
<li class="left-menu">
<a class="active" href="#home">HOME</a>
HOW IT WORKS
WHY CHOOSE US
</li>
</li>
<li class="right-menu">
SERVICES
OUR GALLERY
CONTACT US
</li>
</section>
<section id="secondpage">
</section>
Note:
I have added position: relative to first section (.section0) for z-index to work.
I have remove margin and padding from <body> only to make this snippet clean.
Edit: As you said, the previous example makes the navigation bar slide out from under the first section, you can try this example using position: sticky.
I'll explain what I did here.
I took the navigation bar (<ul>) out of home section.
I have wrapped the element <ul>, home and secondpage in an element and gave it a class called wrapper.
The first section remains out of the wrapper.
I have applied position: sticky; to navigation (<ul>) and added a top value at which the navigation should stay fixed.
I have also added position: relative; to wrapper class for the sticky element to work.
This means the navigation bar (<ul>) stays fixed inside the wrapper class.
Working Example:
body {
margin: 0;
padding: 0;
}
#section0 {
width: 100%;
height: 100vh;
background-color: blue;
position: relative;
}
#home {
width: 100%;
height: 100vh;
background-color: white;
display: block;
margin: 0 auto;
}
ul {
background: #fff;
display: grid;
grid-template-columns: 1fr auto 1fr;
align-items: center;
z-index: 9999;
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: black;
position: -webkit-fixed;
/* Safari */
/*position: fixed;*/
position: sticky;
top: 0;
}
ul li.left-menu {
display: flex;
justify-content: flex-end;
}
ul li.right-menu {
display: flex;
justify-content: flex-start;
}
ul li a {
display: block;
color: white;
text-align: center;
padding: 13px 20px;
text-decoration: none;
font-family: Futura;
font-size: 8px;
}
li a:hover {
color: #00CFFF;
}
.active {
color: #00CFFF;
}
#secondpage {
height: 100vh;
width: 100%;
background-color: orange;
}
.wrapper {
position: relative;
}
<section id="section0">
</section>
<div class="wrapper">
<ul>
<li class="left-menu">
<a class="active" href="#home">HOME</a>
HOW IT WORKS
WHY CHOOSE US
</li>
<li class="right-menu">
SERVICES
OUR GALLERY
CONTACT US
</li>
</ul>
<section id="home">
</section>
<section id="secondpage">
</section>
</div>
How can I align 2 different Component side by side using flexbox ?
I have my 1st component "nav-menu" and the 2nd "homepage" I would like it to be side by side.
homepage.component.html
<app-nav-menu></app-nav-menu>
<div class="container">
<div>
<img src="https://colorlib.com/preview/theme/amado/img/product-img/pro-big-1.jpg">
</div>
</div>
I gave a width to my container
homepage.component.css
.container {
display: flex;
width: 50%;
}
div.container>div {
flex-grow: 1;
}
img {
width: 20%;
height: auto;
}
nav-menu.component.html
<h1>Furniture</h1>
<nav class="nav" role="navigation">
<ul clas="menu">
<li>Home</li>
<li>Shop</li>
<li>Product</li>
<li>Cart</li>
</ul>
</nav>
I gave a width to my nav
nav-menu.component.css
* {
box-sizing: border-box;
}
h1 {
display: flex;
justify-content: space-between;
margin-left: 30px;
margin-bottom: 100px;
}
nav {
width: 40%;
}
.nav ul {
margin: 0px;
padding: 0px;
background: white;
list-style: none;
}
.nav a {
display: flex;
flex-direction: column;
align-items: flex-start;
padding: 0.5em;
text-decoration: none;
color: black;
font-size: 2em;
width: 10px;
}
.nav a:hover {
color: #FFA500;
transition: 0.1s;
}
whats the next step ?
thanks.
you have to wrap your both components in a flex
<div style="display: flex; flex-grow: grow">
<app-component-1></app-component-1>
<app-component-2></app-component-2>
</div>
I've been trying to make a page with a fixed transparent header, using flexbox. At first, I found that somehow this causes a confliction (the fixed positioning and the flex) and the justify-content or align-items properties won't work on the child elements of the wrapper flex-fixed parent. The child elements of the fixed parent won't space appropriately.
But then I saw this https://templated.co/industrious, and somehow it works!
So I cannot understand why it doesn't work with my code. It seems to me I'm not doing it differently.
The header-fixed-flex div wraps the LOGO, NAV and search (svg) elements, but I cannot make the justify-content or align-items option to work on header-nav and navigation div's.
body {
height: 2500px;
}
.header-fixed-flex {
max-width: 150rem;
width: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 100;
display: flex;
justify-content: space-between;
transform: translate(19.2rem, 0);
}
.header_nav {
max-width: 155rem;
display: flex;
justify-content: space-around;
align-items: center;
}
.header_logo {
max-height: 9.7rem;
background: rgba(3, 12, 77, 0.4);
}
.header_link {
padding: 0.5rem;
}
.navigation {
background: rgba(191, 218, 218, 0.4);
display: flex;
}
.navigation_list {
list-style: none;
letter-spacing: 0.4rem;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
align-items: center;
height: 100%;
}
.navigation_item:not(:last-child) {
margin-right: 3rem;
}
.navigation_link:link, .navigation_link:visited {
color: #fff;
text-decoration: none;
padding: 0.8rem;
}
.navigation_button {
border: none;
background: none;
display: flex;
align-items: center;
}
.navigation_search-input {
border: none;
background: rgba(255, 255, 255, 0.1);
outline: none;
width: 5rem;
}
.navigation_icon {
padding: 0.5rem;
width: 3rem;
fill: #fff;
}
.hero_img {
background: url(https://twimg0-a.akamaihd.net/a/1350072692/t1/img/front_page/jp-mountain#2x.jpg) top/cover;
height: 100vh;
}
<div class="header-fixed-flex">
<div class="header_nav">
<header class="header_logo">
LOGO
</header>
<nav class="navigation">
<ul class="navigation_list">
<li class="navigation_item">
Profile
</li>
<li class="navigation_item">
Services
</li>
<li class="navigation_item">
Articles
</li>
<li class="navigation_item">
Contact
</li>
</ul>
<button class="navigation_button">
<input type="text" class="navigation_search-input" id="search-query"/>
<label for="search-query" class="navigation_search_label"></label>
<svg class="navigation_icon"></svg>
</button>
</nav>
</div>
</div>
<section class="hero">
<div class="hero_img"></div>
</section>
Or a codepen link with scss
https://codepen.io/tantoniou/pen/QoGmba
Remove the header-fixed-flex element and apply this style on header_nav
width: 100%;
top: 0;
left: 0;
position: fixed;
z-index: 100;
display: flex;
justify-content: space-between;
It's really tough to determine what you want from your writeup with no design comp or wireframe provided, but my initial guess is things aren't happening as you expect because .header-fixed-flex only has one child. So maybe setting flex: 1 or just width: 100% on .header_nav will get things working as you like.