I have a menu grid layout with an inner item (in this case it's the .metadata div) that I want to expand and push down another item. See example here :
.wrapper {
display: grid;
grid-column-gap: 8px;
grid-row-gap: 4px;
grid-template-columns: 48px minmax(0px, 3fr) 1fr;
grid-template-rows: 24px 20px 44px;
grid-template-areas:
"icon title action-bar"
"icon metadata action-bar"
"tabs .... bottom-right";
padding: 16px 16px 0 16px;
}
.metadata {
grid-area: metadata;
display: flex;
align-items: baseline;
direction: ltr;
}
.innterTest {
height: 100px;
background-color: red;
}
.metadataItem {
display: flex;
}
.tabs {
grid-area: tabs;
grid-column-end: 3;
padding-top: 4px;
}
<div class="wrapper">
<div class="icon">icon
</div>
<div class="title">TITLE
</div>
<div class="action-bar">action bar
</div>
<div class="metadata">
<div class="metadataItem">
data node 1
<div class="innterTest">
testing
</div>
</div>
<div class="metadataItem">
data node 2
</div>
<div class="metadataItem">
data node 3
</div>
<div class="metadataItem">
data node 4
</div>
</div>
<div class="tabs">tabs
</div>
</div>
https://jsfiddle.net/c8wx2bgn/
If you inspect the outer .metadata wrapping div it seems to stay a small size. What I would like to happen is for it to expand and push down the .tabs grid item. The general grid layout has been working as I had hoped, but I've added more items inside metadata and want it to push tabs down when it expands.
I've tried enforcing a height on the metadata and metadata divs but this does not seem to effect the layout. New to grid so unsure what I am missing here.
You have grid-template-rows: 24px 20px 44px.
This means that the second row, which contains your metadata div, is limited in height to 20px.
Try this: grid-template-rows: 24px auto 44px.
Related
I was searching a way to make a responsive design like so
I have 3 divs inside a parent div
<div style="display: flex">
<div class="logo">some image here</div>
<div class="menu-items">
Home
...
</div>
<div class="login-logout">Here is the login component</div>
</div>
How can I make a responsive version of this to be something like this using only css and sass?
<div style="display: flex; flex-direction: column">
<div style="display: flex">
<div class="logo">some image here</div>
<div class="login-logout">Here is the login component</div>
</div>
<div class="menu-items">
Home
...
</div>
</div>
I want the middle div to stay bellow the other two
I have a guess that this can be possible using grid layout, but honestly I don't understand very much about it and prefer using flex. So if this could be achieved using flex I would be very much appreciated
Edit:
An image of how I want the layout to be.
flex is basically one dimensional whereas grid allows layout in two dimensions.
This snippet takes your code but sets the container to display grid.
grid-template areas are laid out for the wider screens in the ratio 2/3/1 and in the narrower ones in the ratio 2/1 in the top line.
Obviously you'll want to set the relative sizes suitable for your particular case.
.container {
width: 100vw;
display: grid;
grid-template-columns: repeat(6, 1fr);
grid-template-areas: 'logo logo menu menu menu login';
gap: 2vw;
padding: 2vw;
box-sizing: border-box;
}
.container>* {
border: 3px solid;
box-sizing: border-box;
}
#media (max-width: 768px) {
.container {
grid-template-columns: repeat(3, 1fr);
grid-template-areas: 'logo logo login' 'menu menu menu';
}
}
.logo {
grid-area: logo;
}
.menu-items {
grid-area: menu;
}
.login-logout {
grid-area: login;
}
/* borders added fordemo */
.logo {
border-color: red;
}
.menu-items {
border-color: blue;
}
.login-logout {
border-color: green;
}
<div class="container">
<div class="logo">some image here</div>
<div class="menu-items">
Home ...
</div>
<div class="login-logout">Here is the login component</div>
</div>
This question already has answers here:
Targeting flex items on the last or specific row
(10 answers)
Closed 1 year ago.
I have a container with a dynamic number of items.
Each line can contain up to 4 items. If there are more than 4 items, the next item will start a new line (image 1). If there are less than 4 items it's OK, they just won't fill the whole line (image 2).
But I'm having troubles with the spaces between them:
I tried to use margin-right but it affects the last items in the lines (e.g.: item #4).
I tried to use justify-content: space-between but it looks good only for 4 items and up. For 3 and bellow, it creates a big space between them and I want them to look as in image 2.
Any other elegant / easy solutions?
.container {
display: flex;
flex-wrap: wrap;
/* justify-content: space-between; */
}
.item {
display: inline-block;
width: calc(25% - 12px);
/* margin-right: 12px; */
}
<div class="container">
<div class="item">
#1
</div>
<div class="item">
#2
</div>
<div class="item">
#3
</div>
<div class="item">
#4
</div>
</div>
You can use css grid, you have to use display: grid;, use grid-template-columns to set the amount of columns that you want (1fr = 1 parent container fraction) and finally use grid-gap to set the space between your items.
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
grid-gap: 12px;
}
.item {
display: inline-block;
border: 1px solid red;
color: red;
}
<div class="container">
<div class="item">
#1
</div>
<div class="item">
#2
</div>
<div class="item">
#3
</div>
<div class="item">
#4
</div>
</div>
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
grid-gap: 12px;
}
.item {
display: inline-block;
border: 1px solid red;
color: red;
}
<div class="container">
<div class="item">
#1
</div>
<div class="item">
#2
</div>
<div class="item">
#3
</div>
<div class="item">
#4
</div>
<div class="item">
#5
</div>
<div class="item">
#6
</div>
</div>
More info about Css grid Here!
In class .item, is defined width with calc(25% - 12px). Remember, 25% is just 4 items in each line. 20% is 5 items in each line.
So, change the width to calc(20% - 12px)
While CSS Grid is possibly the better solution for the problem, it's entirely possible to solve the problem with CSS flex-box layout, using the gap property and taking advantage – as did your original code – of the calc() function:
// this is to allow you to dynamically add more .item elements
// so you see that it should meet your needs containing more
// elements.
// we use document.querySelector() to retrieve the first element
// that matches the selector (if any exist, otherwise null):
const button = document.querySelector('button'),
// defining a named function to handle addition of new .item
// elements:
addMore = () => {
// finding the first .item element on the page:
let base = document.querySelector('.item');
// finding the .container element, and using
// .append() to attach a cloned copy of the first
// .item:
document.querySelector('.container').append(base.cloneNode(true));
}
// binding the named - addMore() - function as the event-handler
// for the 'click' event:
button.addEventListener('click', addMore);
*,
::before,
::after {
/* selecting all elements, and the pseudo-elements ::before
and ::after, setting their box-sizing model to border-box
in order that their widths include their border and padding
*/
box-sizing: border-box;
/* removing margin and padding: */
margin: 0;
padding: 0;
}
.container {
display: flex;
flex-wrap: wrap;
/* using the gap property to place a 0.5em 'gutter'
between adjacent elements, both horizontally and
vertically: */
gap: 0.5em;
}
.item {
/* setting the flex-grow: to 1, flex-shrink to 0,
and flex-basis to the result of 20% of the parent-
width minus 0.5em (the gap-space): */
flex: 1 0 calc(20% - 0.5em);
}
/* irrelevant, purely for aesthetics */
*,
::before,
::after {
line-height: 2em;
}
.container {
border: 1px solid #000;
counter-reset: itemCount;
width: 90vw;
margin-inline: auto;
}
.item {
background-color: lightblue;
flex: 1 0 calc(20% - 0.5em);
}
.item:nth-child(odd) {
background-color: palegreen;
}
.item::before {
content: counter(itemCount, decimal-leading-zero);
counter-increment: itemCount;
}
<button type="button">Add another item</button>
<div class="container">
<div class="item">
</div>
<div class="item">
</div>
<div class="item">
</div>
<div class="item">
</div>
</div>
JS Fiddle demo.
References:
box-sizing.
calc().
gap.
margin-inline.
I am using CSS grid for my layout. 2 columns and three rows.
I would like the left column to be flexible so that the left column can contain a navigation bar that is collapsible, meaning that it opens/closes when I click a hamburger-menu button.
So far I have not found any examples.
Is it possible to make a column flexible from width 0 to any pixel width?
You can use min-content in grid-template-columns property and set width of sidebar div, then if you change width of this element, content div should fill the empty space. Check snippet below.
var collapsed = false
$('#btn').click(function() {
$('.sidebar').css('width', !collapsed ? '100px' : '150px')
collapsed = !collapsed
})
.grid-container {
display: grid;
grid-template-columns: min-content 1fr;
grid-template-rows: 1fr;
gap: 0px 0px;
grid-template-areas: "sidebar content";
width: 400px;
height: 300px;
}
.sidebar {
grid-area: sidebar;
background-color: red;
width: 150px;
}
.content {
grid-area: content;
background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="grid-container">
<div class="sidebar">
<button id='btn'>collapse</button>
</div>
<div class="content">content</div>
</div>
I'm trying to align a logo and navigation bar in one row across the top of a website using CSS grid.
I've written out the code but can't work out what I'm doing wrong as to why it's not working: https://codepen.io/chloewb/pen/wRRewQ
.logo{
grid-area: logo;
background:white;}
.navi{
grid-area: navi;
background:Yellow;}
.section1{
grid-area: features;
background:LightSalmon;}
.section2{
grid-area: technology;
background:PaleTurquoise;}
.section3{
grid-area: pricing;
background:LightPink;}
.section4{
grid-area: email;
background:PaleGreen;}
.container {
display: grid;
grid-template-rows: repeat (5, auto);
grid-template-columns: 1fr 1fr 1fr;
font-size: 40px;
width: 100%;
background: grey;
grid-template-areas:
"logo navi navi"
"features features features"
"technology technology technology"
"pricing pricing pricing"
"email email email";}
The first thing to notice is that, when you use display: grid on a container element, its direct children will become grid-items, and to these items is that the grid layout you build will apply.
So let's say we have the following:
<div class="container">
<div class="child-1">
<div class="child-2"></div>
<div class="child-2"></div>
</div>
<div class="child-1"></div>
<div class="child-1"></div>
<div class="child-1"></div>
</div>
And this CSS:
.container{
display: grid;
}
Then only the child-1 will become grid items and be able to get properties like grid-area applied to them; everything else inside .child-1, like .child-2 will behave normally, as if there's no Grid. Unless you also specify the .child-1 element to be a grid with display: grid.
In your case, you header element is a direct child of the .container element, so it is a grid item and can be positioned on any place on the grid, but the logo and navi elements are children of header, so the grid layout does not apply to them. You would either have to take them out of the header so the rules you wrote take effect, or create another grid in the header and let it use the full first row. See this example and notice how the nesting of the elements affect them.
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: minmax(50px, auto);
grid-template-areas: "logo navi navi";
margin-bottom: 20px;
border: 1px solid black;
}
.logo {
border: 1px solid red;
grid-area: logo;
}
.navi {
border: 1px solid blue;
grid-area: navi;
}
<div class="container">
<div class="logo">Logo</div>
<div class="navi">Nav</div>
</div>
<div class="container">
<header>
<div class="logo">Logo</div>
<div class="navi">Nav</div>
</header>
</div>
I'm trying to create a CSS Grid which centers all its items both horizontally and vertically and maintains a background which takes up the whole grid.
To do this, I am first creating CSS for each item which looks something like this:
.item1 {
grid-area: header;
background:yellow;
text-align: center;
align-items: center;
display: grid;
}
The only difference between each item is its item number (in the class), the grid-area name, and the background color. I added display: grid; because without it I can't seem to both center and have the background color cover the whole grid. I don't understand why this is, but it seems to work.
My container CSS looks like this:
.container {
display: grid;
grid-template-columns: 20vw 20vw 20vw 20vw;
grid-template-rows: 25vh 25vh 25vh;
grid-template-areas:
"header header header header"
"main main subg sidebar"
"footer footer footer footer";
}
Now when I create the grid everything looks the way I want it to:
<div class="container">
<div class="item1"><H1>Header</H1></div>
<div class="item2">Main</div>
<div class="item3">Sidebar</div>
<div class="item4">Footer</div>
<div class="item5">X</div>
</div>
Now I want to achieve the exact same effect in the central item. So first I create nearly identical CSS tags for the sub-items and sub-containers. The only differences are in the naming and changing the dimensions from absolute screen based (vh/vw) to percentages:
.sub_item1 {
grid-area: header1;
background:yellow;
text-align: center;
align-items: center;
display: grid;
}
...
.sub_container {
display: grid;
grid-template-columns: 25% 25% 25% 25%;
grid-template-rows: 33% 33% 33%;
grid-template-areas:
"header1 header1 header1 header1"
"main1 main1 subg1 sidebar1"
"footer1 footer1 footer1 footer1";
}
I nest the sub-container in the center item in the top-level container:
<div class="container">
<div class="item1"><H1>Header</H1></div>
<div class="item2">Main</div>
<div class="item3">Sidebar</div>
<div class="item4">Footer</div>
<div class="item5 sub_container">
<div class="sub_item1">Header</div>
<div class="sub_item2">Main</div>
<div class="sub_item3">Side</div>
<div class="sub_item4">Footer</div>
<div class="sub_item5">X</div>
</div>
</div>
I have created a fiddle to demonstrate how it fails. The sub-container does not stretch the background color to fit the cells like the top-level does.
I tried changing the dimensions to screen based (e.g. 5vw, 11vh) and this does not work either.
Remove the "item5" class from the sub-container div.
<div class="sub_container">
Here is the updated fiddle.