I have the following setup:
.layout {
display: flex;
flex-direction: column;
height: 100vh;
}
.appbar {
background-color: blue;
color: white;
}
.sidebar {
flex-grow: 1;
overflow-y: auto;
}
.drawer-container {
height: 100%;
display: flex;
}
.drawer {
position: relative;
background-color: #272b34;
color: lightgray;
border-style: none;
align-self: stretch;
overflow-y: auto;
}
.list {
list-style: none;
padding: 1rem;
}
.drawer-content {
padding: 1rem 1rem 1rem 1rem;
margin-top: 1px;
align-self: stretch;
background-color: #eef5f9;
overflow: auto;
flex: 1 1 auto;
}
.component {
background-color: white;
height: 100%;
box-shadow: 0px 0px 3px 1px rgb(0 0 0 / 10%);
overflow: auto;
border-radius: 4px;
}
.header {
padding: 1rem 1rem 1rem;
background-color: #f8f9fa;
}
.grid-container {
margin: 1rem 1rem;
height: calc(100% - 82px);
background-color: red;
}
.grid {
background-color: yellow;
max-height: 100%;
overflow: auto;
}
.grid-content {
height: 500px;
}
<div id="layout" class="layout">
<div id="appbar" class="appbar">
APPBAR
</div>
<div id="sidebar" class="sidebar">
<div id="drawercontainer" class="drawer-container">
<div id="drawer" class="drawer">
<ul class="list">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
<li>item 5</li>
</ul>
</div>
<div id="drawercontent" class="drawer-content">
<div id="component" class="component">
<div class="header">HEADER</div>
<div class="grid-container">
<div class="grid">
<div class="grid-content">GRID CONTENT</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
The question is about this piece of css:
.grid-container {
margin: 1rem 1rem;
height: calc(100% - 82px);
background-color: red;
}
Setting the height like this, I can avoid, that the component element has a scrollbar. It means, the grid-container and the header have a total height of the component. But if I test it with different screen size / pixel ratio, I get a scrollbar (with little scrolling). Note, that the component has to have the property overflow set.
The question is, how can I avoid to set the height this way? How can I avoid the use of pixels or any other units? Basically, I want that the grid-container fills always the remaining area from the component element on any screen sizes / resolutions, without showing any scrollbar, it means not extending it.
Hopefully this snippet does what you want:
Sane default of box-sizing: border-box on every element
Removed stupid margin on the body which caused pagewide scrollbar on 100vh height
Swapped margin on grid-container for padding
Tidied up some shorthands etc. padding: 1rem 1rem 1rem 1rem -> padding: 1rem are the same
* {
box-sizing: border-box;
}
body {
margin: 0;
}
.layout {
display: flex;
flex-direction: column;
height: 100vh;
}
.appbar {
background-color: blue;
color: white;
}
.sidebar {
flex-grow: 1;
overflow-y: auto;
}
.drawer-container {
height: 100%;
display: flex;
}
.drawer {
position: relative;
background-color: #272b34;
color: lightgray;
border-style: none;
align-self: stretch;
overflow-y: auto;
}
.list {
list-style: none;
padding: 1rem;
}
.drawer-content {
padding: 1rem;
margin-top: 1px;
align-self: stretch;
background-color: #eef5f9;
overflow: auto;
flex: 1 1 auto;
}
.component {
height: 100%;
box-shadow: 0px 0px 3px 1px rgb(0 0 0 / 10%);
overflow: auto;
border-radius: 4px;
}
.header {
padding: 1rem;
background-color: #f8f9fa;
}
.grid-container {
padding: 1rem;
height: calc(100% - 82px);
}
.grid {
background-color: yellow;
max-height: 100%;
overflow: auto;
}
.grid-content {
height: 500px;
}
<div id="layout" class="layout">
<div id="appbar" class="appbar">
APPBAR
</div>
<div id="sidebar" class="sidebar">
<div id="drawercontainer" class="drawer-container">
<div id="drawer" class="drawer">
<ul class="list">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
<li>item 5</li>
</ul>
</div>
<div id="drawercontent" class="drawer-content">
<div id="component" class="component">
<div class="header">HEADER</div>
<div class="grid-container">
<div class="grid">
<div class="grid-content">GRID CONTENT</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Related
I try to chamfer the middle of the menu but I can't find how to do it in CSS.
Here is what I would like :
Didn't found a good way to do it.
Tried with some pseudo elements and bottom-left & bottom-right radius.
I could take the logo with the bottom things I guess, but I'm pretty sure it's possible to do it CSS way, but I can't find how.
Here is how I structured it :
* {
box-sizing: border-box;
}
ul,
li {
list-style: none;
line-height: 1;
display: inline-block;
}
.header {
line-height: 1;
padding-top: 15px;
background-color: #FFF;
}
.header>div {
display: grid;
grid-column-gap: 90px;
align-items: center;
grid-template-columns: 1fr auto 1fr;
grid-template-areas: "left center right";
}
.header ul.menu>li:not(:first-child) {
margin-left: 35px;
}
.header li {
display: inline-block;
}
.header__left {
grid-area: left;
justify-self: right;
}
.header__center {
grid-area: center;
}
.header__right {
grid-area: right;
}
<header class="header">
<div class="container">
<div class="header__left">
<ul class="menu">
<li>Menu 1</li>
<li>Menu 2</li>
</ul>
</div>
<div class="header__center">
Logo
</div>
<div class="header__right">
<ul class="menu">
<li>Menu 1</li>
<li>Menu 2</li>
</ul>
</div>
</div>
</header>
I'm not sure what went wrong with your attempt at using pseudo-elements, but this seems to work. You might need to fiddle with margins, padding, and position a bit.
* {
box-sizing: border-box;
}
body {
min-height: 100vh;
margin: 0;
padding: 0;
background-image: url(https://picsum.photos/1600);
background-size: cover;
background-color: pink;
}
ul,
li {
list-style: none;
line-height: 1;
display: inline-block;
}
.header {
line-height: 1;
padding: 0 0 5px;
margin-top: 15px;
position: relative;
overflow: hidden;
}
.header .container {
background-color: #fff;
position: relative;
padding-top: 10px;
margin-bottom: 20px;
}
.header::before {
content: '';
position: absolute;
width: 120px;
height: 120px;
border-radius: 60px;
left: 50%;
transform: translateX(-50%);
top: -35px;
background: #fff;
overflow: hidden;
}
.header>div {
display: grid;
grid-column-gap: 90px;
align-items: center;
grid-template-columns: 1fr auto 1fr;
grid-template-areas: "left center right";
}
.header ul.menu>li:not(:first-child) {
margin-left: 35px;
}
.header li {
display: inline-block;
}
.header__left {
grid-area: left;
justify-self: right;
}
.header__center {
grid-area: center;
}
.header__right {
grid-area: right;
}
<header class="header">
<div class="container">
<div class="header__left">
<ul class="menu">
<li>Menu 1</li>
<li>Menu 2</li>
</ul>
</div>
<div class="header__center">
<img src="https://via.placeholder.com/50" />
</div>
<div class="header__right">
<ul class="menu">
<li>Menu 1</li>
<li>Menu 2</li>
</ul>
</div>
</div>
</header>
Fiddle demo
I was experimenting with flexbox on IE and noticed that my navigation bar does not work the same on IE compared to all other browsers.
The navigation bar should appear on two lines as soon as the buttons on the right don't fit in the space right next to the logo. If it doesn't fit, it's pushed on the second line with flex-wrap: wrap. And when it's pushed to the second line it centers all buttons over the entire width of the screen.
I fixed this by using a high flex-grow number on the spacer between the logo and the navigation bar. This works well on chrome, edge, etc, but not on internet explorer 11.
The demo I use for to test this:
https://jsfiddle.net/td2rq4h1/
*{
box-sizing: border-box;
}
body{
background: red;
}
.logo{
background-color: yellow;
width: 145px;
height: 70px;
margin-right: 100px;
}
#headermenu{
background-color: gray;
.telephone {
border: 3px solid pink;
width: 145px;
height: 30px;
margin-right: 100px;
}
}
#menu{
background-color: blue;
}
.spacer {
flex-grow: 1000;
background-color: green;
display: flex;
flex-wrap: wrap;
}
.inner-spacer {
flex-grow: 1;
flex-basis: 100%;
}
.link {
flex-grow: 0;
}
nav{
border: 5px solid black;
flex: 1 1;
display: flex;
justify-content: center;
}
ul{
list-style: none;
margin: 0;
padding: 0;
text-align: center;
}
li{
border: 2px solid purple;
background-color: white;
padding: 1em;
white-space: pre;
margin: 0;
display: inline-block;
}
<div id="menu" class="d-flex flex-wrap">
<div class="logo">Logo</div>
<div class="spacer"></div>
<nav>
<ul class="d-flex flex-row">
<li>Home</li>
<li>Nav item 1</li>
<li>Nav item 2</li>
<li>Nav item 3</li>
<li>Nav item 4</li>
<li>Nav item 5</li>
</ul>
</nav>
</div>
Can anybody explain me why this happens and how i could resolve this? Thanks
you may reduce the use of flex: x properties and play with margin instead ... hudge flex value..
example forked from the broken jsfiddle:
* {
box-sizing: border-box;
}
.d-flex {
display: flex;
}
.flex-wrap {
flex-wrap: wrap;
}
body {
background: red;
}
.logo {
background-color: yellow;
width: 145px;
height: 70px;
margin-right: 100px;
}
#headermenu {
background-color: gray;
}
#headermenu .telephone {
border: 3px solid pink;
width: 145px;
height: 30px;
margin-right: 100px;
}
#menu {
background-color: blue;
}
.spacer {
flex-grow: 1;
background-color: green;
display: flex;
}
nav {
border: 5px solid black;
display: flex;
justify-content: center;
margin: 0 auto;
}
nav ul {
list-style: none;
margin: 0 auto;
padding: 0;
text-align: center;
}
nav ul li {
border: 2px solid purple;
background-color: white;
padding: 1em;
white-space: pre;
margin: 0;
display: inline-block;
}
<div id="menu" class="d-flex flex-wrap">
<div class="logo">Logo</div>
<div class="spacer"></div>
<nav>
<ul class="d-flex flex-row">
<li>Home</li>
<li>Nav item 1</li>
<li>Nav item 2</li>
<li>Nav item 3</li>
<li>Nav item 4</li>
<li>Nav item 5</li>
</ul>
</nav>
</div>
explanation : IE11 will be soon a decade old and did not update bugs on its flex implementation since. it's been edge since, and even edge will stop being updated.
I made a flexbox card using HTML, CSS. I should add a dropdown menu to the bottom of the card below the footer section, which is shown by clicking the button. I tried but can not get a menu of the same width as a card and right position. How can I achive this?
function showMenu() {
document.getElementById('dropdown').classList.toggle('show');
}
.card {
display: flex;
flex-direction: column;
height: 300px;
width: 200px;
border: 1px solid black;
position: relative;
}
.card .header {
display: flex;
flex: 2;
justify-content: center;
align-items: center;
}
.card .body {
display: flex;
flex: 5;
justify-content: center;
align-items: center;
border-bottom: 1px solid black;
border-top: 1px solid black;
}
.card .footer {
display: flex;
flex: 2;
justify-content: center;
align-items: center;
}
.dropdown-content {
display: none;
flex: 2;
position: absolute;
background-color: blue;
overflow: none;
z-index: 999;
color: #ffffff;
flex-direction: column;
}
.show {
display: block;
}
<div class="card">
<div class="header">
Header
</div>
<div class="body">
Body
</div>
<div class="footer">
<button onclick="showMenu()">Toggle Menu</button>
</div>
<ul id="dropdown" class="dropdown-content">
<li>Menu 1</li>
<li>Menu 2</li>
<li>Menu 3</li>
<li>Menu 4</li>
</ul>
</div>
I need dropdown menu same size as card and positioned below footer
Add top: 100%, box-sizing: border-box and margin: 0 to the menu.
function showMenu() {
document.getElementById('dropdown').classList.toggle('show');
}
.card {
display: flex;
flex-direction: column;
height: 300px;
width: 200px;
border: 1px solid black;
position: relative;
}
.card .header {
display: flex;
flex: 2;
justify-content: center;
align-items: center;
}
.card .body {
display: flex;
flex: 5;
justify-content: center;
align-items: center;
border-bottom: 1px solid black;
border-top: 1px solid black;
}
.card .footer {
display: flex;
flex: 2;
justify-content: center;
align-items: center;
}
.dropdown-content {
margin: 0;
box-sizing: border-box;
display: none;
position: absolute;
top: 100%;
width: 100%;
flex: 2;
background-color: blue;
overflow: none;
z-index: 999;
color: #ffffff;
flex-direction: column;
}
.show {
display: block;
}
<div class="card">
<div class="header">
Header
</div>
<div class="body">
Body
</div>
<div class="footer">
<button onclick="showMenu()">Toggle Menu</button>
</div>
<ul id="dropdown" class="dropdown-content">
<li>Menu 1</li>
<li>Menu 2</li>
<li>Menu 3</li>
<li>Menu 4</li>
</ul>
</div>
FOR EXAMPLE, SEE THIS PEN
I have 6 menu items and I want to achieve this grid layout without nesting. I'm a newbie in CSS grid and I thought using the CSS grid will be the best way to achieve what in the design.
This is what I have done so far.
ul {
list-style: none;
padding-left: 0;
}
.menu-items {
text-align: center;
display: grid;
grid-template-columns: 100%;
grid-template-rows: repeat(3, 33.33%);
}
.menu-items {
width: 100%;
height: 100vh;
overflow: hidden;
position: fixed;
top: 0;
left: 0;
grid-template-columns: 1fr 1fr;
grid-template-rows: 50% 50%;
grid-template-areas: "item1 item2" "item3 item4";
}
.menu__item {
height: 100%;
background: #212528;
border: 1px solid #333;
display: flex;
justify-content: center;
align-items: center;
}
.menu__item--1 {
grid-area: item1;
}
.menu__item--2 {
grid-area: item2;
}
.menu__item--3 {
grid-area: item3;
}
.menu__item--4 {
grid-area: item3;
}
.menu__item--5 {
grid-area: item3;
}
.menu__item--6 {
grid-area: item4;
}
.menu__item--3,
.menu__item--4,
.menu__item--5 {
display: block;
}
.menu-item-inner {
align-items: center;
}
.mainmenu {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.mainmenu {
counter-reset: menuitem;
}
.mainmenu__item {
text-transform: lowercase;
overflow: visible;
margin: 0.5rem 0;
padding: 0 0.5rem;
position: relative;
transition: color 0.3s;
}
.mainmenu__item:hover {
color: cyan;
}
.mainmenu__item:hover::after {
opacity: 1;
transform: scale3d(1, 1, 1);
}
ul.menu-items {
margin: 0;
padding: 0;
}
.mainmenu__item {
position: relative;
overflow: hidden;
transition: color 0.1s;
margin: 0.25rem 0;
display: block;
color: #fff;
font-size: 32px;
font-weight: 800;
}
<ul class="menu-items">
<li class="menu__item menu__item--1">
<div class="menu-item-inner">
<div class="mainmenu">
Menu 1
</div>
</div>
</li>
<li class="menu__item menu__item--2">
<div class="menu-item-inner">
<div class="mainmenu">
Menu 2
</div>
</div>
</li>
<li class="menu__item menu__item--3">
<div class="menu-item-inner">
<div class="mainmenu">
Menu 3
</div>
</div>
</li>
<li class="menu__item menu__item--4">
<div class="menu-item-inner">
<div class="mainmenu">
Menu 4
</div>
</div>
</li>
<li class="menu__item menu__item--5">
<div class="menu-item-inner">
<div class="mainmenu">
Menu 5
</div>
</div>
</li>
<li class="menu__item menu__item--6">
<div class="menu-item-inner">
<div class="mainmenu">
Menu 6
</div>
</div>
</li>
</ul>
CODPEN
Can anyone please guide me achieving this layout using CSS-Grid without nesting
(Changing the visual order without changing the logical order of the
document)
You can use grid-template-areas if you want complex layout:
* {
box-sizing: border-box;
}
body {
margin: 0;
display: flex;
align-items: center;
justify-content:center;
height: 100vh;
min-height: 600px;
}
.box {
display: flex;
align-items: center;
justify-content:center;
border: 1px solid #333;
background: #444;
color: #f9f9f9;
font-size: 2rem;
font-family: Open-sans, Arial, sans-serif;
}
.container {
width: 800px;
height: 100%;
display: grid;
padding: .5rem;
grid-gap: .5rem;
/* This is where Grid is defined*/
grid-template-areas:
'box-1 box-1 box-2 box-2'
'box-1 box-1 box-2 box-2'
'box-3 box-5 box-6 box-6'
'box-4 box-5 box-6 box-6';
}
.box-1 {
grid-area: box-1;
}
.box-2 {
grid-area: box-2;
}
.box-3 {
grid-area: box-3;
}
.box-4 {
grid-area: box-4;
}
.box-5 {
grid-area: box-5;
}
.box-6 {
grid-area: box-6;
}
<div class="container">
<div class="box box-1">1</div>
<div class="box box-2">2</div>
<div class="box box-3">3</div>
<div class="box box-4">4</div>
<div class="box box-5">5</div>
<div class="box box-6">6</div>
</div>
I need to create a web page that uses 100vh, or takes up 100% of the screen height and width (no scroll). I created a container(height:100vh) that holds everything in it, and within that container, I need everything in there to be responsive.
Design concept:
The outer container height is 100vh and I need the inner container to be responsive:
#root {
position: relative;
height: 100vh;
overflow: hidden;
}
#root-inner-container {
width: 100%;
}
The problem I run into is by using 100vh, the content inside the container does not stay responsive and tends to overflow.
Jsfiddle to what I have so far: https://jsfiddle.net/fm6hmgpk/
Flex Solution
body {
margin: 0;
color: white;
}
.container {
background: grey;
width: 100vw;
height: 100vh;
}
.navbar {
height: 15vh;
background: darkblue;
margin: 0 10px;
}
.bottom {
background: lightgrey;
height: 85vh;
margin: 0 10px;
display: flex;
}
.left-bottom {
background: red;
width: 70%;
display: flex;
flex-direction: column;
}
.right-bottom {
flex: 1;
background: lightgrey;
}
.content-list {
display: flex;
height: 80%;
background: maroon;
}
.text {
flex: 1;
background: green;
}
.content {
width: 80%;
background: orange;
}
.list {
flex: 1;
}
<div class="container">
<div class="navbar">
NAVBAR
</div>
<div class="bottom">
<div class="left-bottom">
<div class="content-list">
<div class="content">
CONTENT
</div>
<div class="list">
LIST
</div>
</div>
<div class="text">
TEXT
</div>
</div>
<div class="right-bottom">
IMAGE
</div>
</div>
</div>
Calculation: (For scrolling issue)
<body> default margin:8px; and your border:2px solid black;
Sums up to 10px so we need to deduct twice of 10px
Hence height: calc(100vh - 20px);
EDIT:
To make it responsive you need to get rid of fixed px value to your li
li {}
#root {
display: flex;
position: relative;
height: calc(100vh - 20px);
border: 2px solid black;
}
#root-inner-container {
flex: 1;
width: 100%;
display: flex;
}
.app-container {
flex: 1;
display: flex;
}
.div-1,
.div-2 {
flex: 1;
display: flex;
}
ul {
flex: 1;
display: flex;
flex-direction: column;
}
li {
flex: 1;
border: 1px solid red;
}
<div id="root">
<div id="root-inner-container">
<div class="app-container">
<div class="div-1">
<ul>
<li>div 1 - One</li>
<li>div 1 - Two</li>
<li>div 1 - Three</li>
<li>div 1 -Four</li>
</ul>
</div>
<div class="div-2">
<ul>
<li>div 2 - One</li>
<li>div 2 - Two</li>
<li>div 2 - Three</li>
<li>div 2 -Four</li>
</ul>
</div>
</div>
</div>
</div>
You may want to consider using grid. For browser support you can check here.
To learn about using grid, check here.
body {
margin: 0
}
#root {
display: grid;
grid-gap: 10px;
grid-template-columns: 3fr 1fr 3fr;
grid-template-rows: 1fr 3fr 1fr;
background-color: #fff;
color: #444;
width: 100vw;
height: 100vh;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 20px;
font-size: 150%;
}
.navbar {
grid-column: 1 / 4;
grid-row: 1;
}
.content {
grid-column: 1;
grid-row: 2 / 3;
}
.list {
grid-column: 2;
grid-row: 2;
}
.image {
grid-column: 3 / 4;
grid-row: 2 / 4;
}
.text {
grid-column: 1 / 3;
grid-row: 3 / 4;
}
<div id="root">
<div class="navbar box">Navbar</div>
<div class="content box">Content</div>
<div class="list box">List</div>
<div class="image box">Image</div>
<div class="text box">Text</div>
</div>
I think it's because your li height is fixed height so if your root height is less than the sum of those li height it will overflow. you can use vh for them too.