How to have vertical lines seperate css grid elements? - html

I have a grid with 3 columns and want to have two vertical lines to separate the elements.
So far, I simply created two span element and placed them between the grid elements using css.
.vertical_line {
position: absolute;
height: 100%;
width: 2px;
background-color: black;
}
#v1 {
left: 33.33%;
}
#v2 {
left: 66.33%;
}
https://jsfiddle.net/0mg12etr/
Changing the number of columns will be annoying with my method and it works nicely only if the width of the elements are known.
Is there a neater way to achieve this?

Is that what you want? Think its a way you want to do with no spans and using ::after
.grid-container {
width: 100%;
text-align: center;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
.grid-element {
align-self: center;
height: 30px;
margin: 6px;
border: 1px solid black;
}
.grid-element:nth-child(2n+3)::after{
content:'';
width:1px;
height:100%;
display:block;
background-color:black;
position:absolute;
margin-left:-7px;
top:0;
}
#v1 {
left: 33.33%;
}
#v2 {
left: 66.33%;
}
<html>
<body>
<div class="grid-container">
<div class="grid-element"></div>
<div class="grid-element"></div>
<div class="grid-element"></div>
<div class="grid-element"></div>
<div class="grid-element"></div>
<div class="grid-element"></div>
</div>
</body>
</html>

You can try with flex.
.row {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 100%;
}
.column {
display: flex;
flex-direction: column;
flex-basis: 100%;
flex: 1;
background:rgba(0,0,0,0.1);
text-align:center;
}
.column:nth-child(odd) {
background:rgba(0,0,0,0.3);
}
.column + .column {
border-left:2px solid red;
}
html, body {
height:100%;
margin:0;
padding:0;
}
<div class="row">
<div class="column">
col1 row1
</div>
<div class="column">
col2 row1
</div>
<div class="column">
col3 row1
</div>
</div>
<div class="row">
<div class="column">
col1 row2
</div>
<div class="column">
col2 row2
</div>
<div class="column">
col3 row2
</div>
</div>

You could have your vertical lines be inserted between your different elements instead of having them at the start and using absolute positions. You might need to wrap everything in a container to keep the grid containers and the vertical lines inline.
For exemple something like this :
<div class="global-container">
<div class="grid-container">
<div class="grid-element"></div>
<div class="grid-element"></div>
<div class="grid-element"></div>
<div class="grid-container">
<span class="vertical_line"></span>
<div class="grid-container">
<div class="grid-element"></div>
<div class="grid-element"></div>
<div class="grid-element"></div>
<div class="grid-container">
<span class="vertical_line"></span>
<div class="grid-container">
<div class="grid-element"></div>
<div class="grid-element"></div>
<div class="grid-element"></div>
<div class="grid-container">
<\div>
You'd have to modify some other css tho : https://jsfiddle.net/6ocyr5b9/8/

Related

CSS: What are the behavior rules for a "width: auto" container with inline-flex?

I was trying to create a list / table view with dynamic width using flexbox, and encountered a behavior I couldn't really wrap my head around. The result I'm trying to achieve is a width that fits the content of the list, at its' widest point.
.main {
width: auto;
background: rgb(233, 148, 148);
display: inline-flex;
flex-wrap: wrap;
}
.container {
display: flex;
width: 100%;
}
.label,
.value {
flex: 1;
padding: 4px;
}
.label {
text-align: end;
border-right: 2px solid red;
}
.value {
text-align: start;
}
<div>
<div class="main">
<div class="container">
<div class="label">Some Label</div>
<div class="value">Some value</div>
</div>
<div class="container">
<div class="label">Some label 2</div>
<div class="value">Other val</div>
</div>
<div class="container">
<div class="label">Third label</div>
<div class="value">
<div>N/A</div>
</div>
</div>
</div>
</div>
What it boils down to, is that the width seems to be determined by the total characters count, and not the widest point, as I would expect. You can edit the HTML and remove the N/A, for example, and the width will decrease.
When I switch to display: inline-block with white-space: nowrap, the width is as expected, but the "columns" are not aligned.
.main {
width: auto;
background: rgb(233, 148, 148);
display: inline-block;
white-space: nowrap;
}
.container {
display: flex;
width: 100%;
}
.label,
.value {
flex: 1;
padding: 4px;
}
.label {
text-align: end;
border-right: 2px solid red;
}
.value {
text-align: start;
}
<div>
<div class="main">
<div class="container">
<div class="label">Some Label</div>
<div class="value">Some value</div>
</div>
<div class="container">
<div class="label">Some label 2</div>
<div class="value">Other val</div>
</div>
<div class="container">
<div class="label">Third label</div>
<div class="value">
<div>N/A</div>
</div>
</div>
</div>
</div>
What causes the large width to occur when the display is inline-flex? Is there a way to get the behavior I'm trying to achieve? I know it can probably be resolved with display: grid, but I'm looking for a simpler solution.
I know it can probably be resolved with display: grid, but I'm looking for a simpler solution.
It might be difficult if you do not handle the grid-layout fine enough yet, but it looks not that much complicated if you use the grid system ;)
For the width, look at max-content.
simple example:
.main {
width: max-content;
background: rgb(233, 148, 148);
}
.container {
display: grid;
grid-template-columns: repeat(2, 1fr);
}
.label,
.value {
padding: 4px;
}
.label {
text-align: end;
border-right: 2px solid red;
}
.value {
text-align: start;
}
<div>
<div class="main">
<div class="container">
<div class="label">Some Label</div>
<div class="value">Some value</div>
</div>
<div class="container">
<div class="label">Some label 2</div>
<div class="value">Other val</div>
</div>
<div class="container">
<div class="label">Third label</div>
<div class="value">
<div>N/A</div>
</div>
</div>
</div>
</div>
In the past ,before flex & grid , display would use the table-layout.
.main {
display:table;
background: rgb(233, 148, 148);
}
.container {
display: table-row;
}
.label, .value {
padding: 4px;
display:table-cell;
}
.label {
text-align: end;
border-right: 2px solid red;
}
.value {
text-align: start;
}
<div>
<div class="main">
<div class="container">
<div class="label">Some Label</div>
<div class="value">Some value</div>
</div>
<div class="container">
<div class="label">Some label 2</div>
<div class="value">Other val</div>
</div>
<div class="container">
<div class="label">Third label</div>
<div class="value">
<div>N/A</div>
</div>
</div>
</div>
</div>

How to align multiple divs vertically on the left and one big div in the right?

I have been trying so hard to find a solution to this but I couldnt achieve the desired solution.
I want to have the following:
and this is what I have tried so far:
#outer-div {
width: 100%;
text-align: left;
background-color: #027DB4;
}
#inner-div {
display: inline-block;
margin: auto;
padding: 3px;
}
<div id="outer-div">
<div id="inner-div" class="input-group">
<label>1</label>
<select>
</select>
</div>
<div id="inner-div" class="input-group">
<label>2</label>
<input>
</div>
</div>
<div id="outer-div">
<div id="inner-div" class="input-group">
<label>3</label>
<input>
</div>
</div>
<div id="outer-div">
<div id="inner-div" class="input-group">
<label>4</label>
<input>
</div>
</div>
P.S. I don't want to use float because it ruins everything else in that page.
use flexbox for this kind of stuff
#container {
display: flex;
}
#left {
display: flex;
flex-direction: column;
}
#right {
display: flex;
flex: 1;
margin-left: 5vw;
flex-direction: column;
}
div {
border: solid 2px black;
}
<div id='container'>
<div id='left'>
<div> one</div>
<div> two</div>
<div> three</div>
</div>
<div id='right'>
<div>right</div>
<div>another right</div>
</div>
</div>
DCR is right on with flexbox. You can also use CSS grid and avoid nesting items https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout.
#outer-div {
text-align: left;
background-color: #027DB4;
display: grid;
}
.right-column {
grid-column: 2 / 2;
grid-row: 1 / 4;
}
<div id="outer-div">
<div class="input-group">1</div>
<div class="input-group">2</div>
<div class="input-group">3</div>
<div class="input-group right-column">4</div>
</div>
.box1{
display:flex;
justify-content: space-between;
}
<div class="box1">
<div class="box2">
<div class="div1">1</div>
<div class="div2">2</div>
<div class="div3">3</div>
</div>
`<div class="div4">4</div>`
</div>
If you do want to try CSS Grid, this is a route to try. .right and .left class properties are added to allow more targeted styling, if needed, and borders are added to the parent and container elements to highlight them.
.outer-div {
display: grid;
grid-template-columns: auto auto;
grid-gap: 1em;
padding: 1em;
border: 1px solid red;
}
.inner-div.left {
grid-column: 1;
border: 1px solid blue;
}
.inner-div.right {
grid-column: 2;
grid-row: 1 / span 3;
border: 1px solid green;
}
<div class="outer-div">
<div class="inner-div left">
<label>1</label>
<select>
</select>
</div>
<div class="inner-div left">
<label>2</label>
<input>
</div>
<div class="inner-div left">
<label>3</label>
<input>
</div>
<div class="inner-div right">
<label>4</label>
<input>
</div>
</div>

2 divs - same height different widths, fixed and dynamic

OK, I edited my question and code to easily show what I mean. I need to have:
"menu" - positioned-left, min-height=500px, width=250px - at all times.
"content" - positioned on the right side of "menu", dynamic width to take all remaining space.
Same height for "menu" and "content" at all times. No matter there will be 1 box or 100 inside "content".
"Boxes" should be lined up from left to right and if there are more, they should stretch height of "content" and "menu" should follow the same height.
<div class="header" style="height:150px; background-color:black;" >
</div>
<div class="navbar" style="height:40px; background-color:yellow;" >
</div>
<div class="menu" style="min-height:500px; width:250px; background-color:orange; float:left;" >
</div>
<div class="content" style="height:auto; background-color:blue; float: left; " >
<?php for ($col = 0; $col < 50; $col++)
{
?><div class="box" style="width:80px; height:80px; background-color:white; margin:10px;" ></div><?php
}
?>
</div>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
div {
border: 1px solid black
}
body {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: 150px 40px minmax(500px , 1fr)
}
.header, .navbar {
grid-column: 1 / -1
}
.content {
display: grid;
grid-gap: 20px;
padding: 20px;
grid-template-columns: repeat(auto-fill, 80px);
align-content: start;
justify-content: space-evenly;
}
.box {
width: 80px;
height: 80px;
}
<body>
<div class='header'>
Header
</div>
<div class='navbar'>
Navbar
</div>
<div class='menu'>
Menu
</div>
<div class='content'>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
<div class='box'>box</div>
</div>
</body>
Your goal is easier to achieve with flexbox, as shown in the solution below.
.header {
height: 150px;
background-color: black;
}
.navbar {
height: 40px;
background-color: yellow;
}
.container {
min-height: 500px;
display: flex;
align-items: flex-start;
}
.menu {
min-height: 500px;
height: 100%;
width: 250px;
background-color: orange;
}
.content {
min-height: 500px;
background-color: blue;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
}
.box {
width: 80px;
height: 80px;
background-color: white;
margin: 10px;
}
<div class="header">
</div>
<div class="navbar">
</div>
<div class="container">
<div class="menu">
</div>
<div class="content">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>

How to align cascaded div containers with Flexbox

I am trying to achieve the following layout for a navigation bar with Flexbox. I am stuck with the alignment of the divs. This is how it should like:
This is what i build up with Divs and CSS. But i dont know how to align those divs, so that i get the desired result.
Fiddle
* {
box-sizing: border-box;
}
#nav {
display: flex;
}
#logo {
width: 100px;
heigth: 100px;
background-color: black;
margin-left: 24px;
}
<div id="nav">
<div id="logo">
100x100px Logo
</div>
<div id="left_side">
<div id="top_nav">
<div id="title">TITLE OF PAGE</div>
<div id="menu_swith">SWITCH</div>
</div>
<div id="bottom_nav">
<div class="nav_item">Menu 1</div>
<div class="nav_item">Menu 2</div>
<div class="nav_item">Menu 3</div>
<div class="nav_item">Menu 4</div>
</div>
</div>
</div>
I would add a few more flex containers to some of the child divs. I'd also specify the width and flex-direction on the #left_side div and justify the content on the #top_nav div.
Try the snippet below or see this updated fiddle:
* {
box-sizing: border-box;
}
#nav,
#left_side,
#top_nav,
#bottom_nav {
display: flex;
}
#left_side {
flex-direction: column;
width: 100%;
}
#top_nav {
justify-content: space-between;
}
#logo {
width: 100px;
heigth: 100px;
background-color: black;
margin-left: 24px;
}
<div id="nav">
<div id="logo">
100x100px Logo
</div>
<div id="left_side">
<div id="top_nav">
<div id="title">TITLE OF PAGE</div>
<div id="menu_swith">SWITCH</div>
</div>
<div id="bottom_nav">
<div class="nav_item">Menu 1</div>
<div class="nav_item">Menu 2</div>
<div class="nav_item">Menu 3</div>
<div class="nav_item">Menu 4</div>
</div>
</div>
</div>
There are many good guides to flexbox available. This one is very good: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
Your layout can be achieved by adding the following CSS
fiddle
* {
box-sizing: border-box;
}
#nav {
display: flex;
}
#logo {
width: 100px;
height: 100px;
background-color: black;
margin-left: 24px;
}
#left_side {
display: flex;
flex-direction: column;
flex: 1;
}
#top_nav {
display: flex;
justify-content: space-between;
flex: 1;
}
#bottom_nav {
display: flex;
flex: 1;
}
<div id="nav">
<div id="logo">
100x100px Logo
</div>
<div id="left_side">
<div id="top_nav">
<div id="title">TITLE OF PAGE</div>
<div id="menu_swith">SWITCH</div>
</div>
<div id="bottom_nav">
<div class="nav_item">Menu 1</div>
<div class="nav_item">Menu 2</div>
<div class="nav_item">Menu 3</div>
<div class="nav_item">Menu 4</div>
</div>
</div>
</div>
Flexbox is one way to build the layout. You'll need extra containers to make it work.
However, if you want to keep it really simple, use CSS Grid:
header {
display: grid;
grid-template-columns: 100px 3fr 1fr;
grid-template-rows: 50px 50px;
grid-template-areas: " logo title switch "
" logo nav nav ";
}
#logo { grid-area: logo; }
#title { grid-area: title; }
#menu_switch { grid-area: switch; }
nav { grid-area: nav; display: flex; }
nav > a {
flex: 0 0 75px;
margin: 5px;
border: 2px solid green;
}
/* for demo only */
#logo { background-color: lightgray; }
#title { background-color: pink; }
#menu_switch { background-color: skyblue; }
nav { background-color: lightgreen; }
* { box-sizing: border-box; }
div, a { display: flex; align-items: center; justify-content: center;
text-align: center; }
<header>
<div id="logo">100x100px<br>Logo</div>
<div id="title">Page Title</div>
<div id="menu_switch">Switch</div>
<nav>
<a class="nav_item">Menu 1</a>
<a class="nav_item">Menu 2</a>
<a class="nav_item">Menu 3</a>
<a class="nav_item">Menu 4</a>
</nav>
</header>
jsFiddle demo
For an explanation of the grid rules above and browser support data, see these posts:
CSS-only masonry layout but with elements ordered horizontally
Browser support for CSS Grid

Can't wrap columns in a flexbox flow except under Chrome

How can I fix the max-height of the "content" div. The code works only under Chrome :/
the "content" div should not expand outside the bottom of the window. the items should wrap to the right.
item1 item4 item7
item2 item5 ...
item3 item6
html
<div class="top">
<div class="title">Title</div>
</div>
<div class="wrapper">
<div class="left">
<div class="link">Link</div>
</div>
<div class="content">
<div class="item">Item1</div>
<div class="item">Item2</div>
<div class="item">Item3</div>
<div class="item">Item4</div>
<div class="item">Item5</div>
<div class="item">Item6</div>
<div class="item">Item7</div>
<div class="item">Item8</div>
<div class="item">Item9</div>
<div class="item">Item10</div>
<div class="item">Item11</div>
<div class="item">Item12</div>
<div class="item">Item13</div>
<div class="item">Item14</div>
<div class="item">Item15</div>
<div class="item">Item16</div>
<div class="item">Item17</div>
<div class="item">Item18</div>
<div class="item">Item19</div>
</div>
</div>
</div>
css
html, body { height: 100%; margin: 0px; padding: 0px }
.main {
height: 100%;
max-heigth: 100%; /* not required under chrome, do not works for others */
display: flex;
flex-direction: column;
background-color: red;
color: white;
}
.wrapper {
flex: 1 1 auto;
display: flex;
background-color: silver;
}
.left {
width: 50px;
background-color: lightblue;
}
.content {
flex:1;
display: flex;
flex-flow: column wrap; /* warp only under Chrome */
}
https://jsfiddle.net/L7zzucms/
Change your wrapper rule to this and it works everywhere (tested on Chrome,Firefox,Edge,IE11)
.wrapper {
height: 100%;
display: flex;
background-color: silver;
}
Updated fiddle
I suppose the flex: 1 in content need a height, other than flex: 1 1 auto, from its parent to be able to wrap properly