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>
Related
I have a series of images that are fetched from a database, and when three or more images are added it visually shows the three columns.
When less than three images are present, because I'm using display: grid; it is currently justified to the left of the parent container (in the code example I've just used red boxes to represent the images).
Is there anyway of having it so that when one or two images are present these are justified to the centre of the parent element. I appreciate I could use javascript to detect how many images are present and if it is less than three, add a class and change the wrapper to display: flex, but I wondered if such a layout was possible with CSS only?
Due to the nature of the layout I do need to use CSS Grid when more than three images are present.
Note: I've commented out two of the red boxes in the HTML to show the initial issue when only one red box is present.
Codepen: https://codepen.io/anna_paul/pen/xxXrVJQ
body {
display: flex;
justify-content: center;
margin: 0
width: 100%;
height: 100vh;
}
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 1rem;
max-width: 1250px;
}
.box {
width: 200px;
height: 200px;
background: red;
}
<div class="wrapper">
<div class="box"></div>
<!-- <div class="box"></div>
<div class="box"></div> -->
</div>
Do it like below:
.wrapper {
display: grid;
grid-auto-flow:column; /* column flow */
justify-content:center; /* center everything */
grid-gap: 1rem;
max-width: 600px;
border:1px solid;
margin:10px auto;
}
/* make sure you only have 3 columns*/
.box:nth-child(3n + 1) {grid-column:1}
.box:nth-child(3n + 2) {grid-column:2}
.box:nth-child(3n + 3) {grid-column:3}
/**/
.box {
width: 100px;
height: 100px;
background: red;
}
<div class="wrapper">
<div class="box"></div>
</div>
<div class="wrapper">
<div class="box"></div>
<div class="box"></div>
</div>
<div class="wrapper">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<div class="wrapper">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<div class="wrapper">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<div class="wrapper">
<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>
Because you are using 1fr for each column, even if a column has no content it is taking 33% of the free space. You need to specify units other than fr(fraction of the available space) unit:
grid-template-columns: auto auto auto;
grid-template-columns: repeat(3, auto);
grid-template-columns: repeat(3, minmax(min-content, max-content));
Use any of the above. There is a small difference between auto and minmax(min-content, max-content).
Following is the demo with 3 containers with 1, 2 and >3 items respectively:
body {
margin: 0;
width: 100%;
height: 100vh;
}
.demo {
display: flex;
justify-content: center;
}
.wrapper {
display: grid;
grid-template-columns: repeat(3, minmax(min-content, max-content));
grid-gap: 1rem;
width: auto;
max-width: 1250px;
}
.box {
width: 200px;
height: 200px;
background: red;
border: 1px solid;
}
<p>Grid with one item</p>
<div class="demo">
<div class="wrapper">
<div class="box">1</div>
</div>
</div>
<hr>
<p>Grid with two items</p>
<div class="demo">
<div class="wrapper">
<div class="box">1</div>
<div class="box">2</div>
</div>
</div>
<hr>
<p>Grid with >3 items</p>
<div class="demo">
<div class="wrapper">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
</div>
</div>
The 1rem grid-gap will remain even if the column has 0 width. So in your setup, grid inside flex, the item in one item grid will be off by 2rem(2grid-gaps) from the center. If this is not a big deal then no worries.
But if you want exact center then you need to make grid-gap:0. And use spacing in side grid items(.box) like margin: 0.5rem; or padding:0.5rem to make artificial grid-gap.
body {
margin: 0;
width: 100%;
height: 100vh;
}
.demo {
display: flex;
justify-content: center;
}
.wrapper {
display: grid;
grid-template-columns: repeat(3, minmax(min-content, max-content));
width: auto;
max-width: 1250px;
}
.box {
width: 200px;
height: 200px;
background: red;
border: 1px solid;
margin: 0.5rem;
}
<p>Grid with one item</p>
<div class="demo">
<div class="wrapper">
<div class="box">1</div>
</div>
</div>
<hr>
<p>Grid with two items</p>
<div class="demo">
<div class="wrapper">
<div class="box">1</div>
<div class="box">2</div>
</div>
</div>
<hr>
<p>Grid with >3 items</p>
<div class="demo">
<div class="wrapper">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
</div>
</div>
using auto instead of fr and using align-content solve your problem.
body {
display: flex;
justify-content: center;
margin: 0
width: 100%;
height: 100vh;
}
.wrapper {
display: grid;
grid-template-columns: auto auto auto;
align-content : start;
/* grid-gap: 1rem; */
max-width: 1250px;
}
.box {
width: 200px;
height: 200px;
background: red;
margin: 1rem ;
}
<div class="wrapper">
<div class="box"></div>
<!-- <div class="box"></div>
<div class="box"></div> -->
</div>
I have a layout that is a sidebar and a grid both wrapped in a flexbox. I'd like to put a div underneath the grid so it can have prev/next buttons, like in this image, but I can't figure out how to do that. The grid resizes itself with the window so the grid can take as many rows as necessary and then the div should go below that, and be as wide as the grid.
This is what I have, but the div is on the right of the grid:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Boardgame Database</title>
<style>
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
aside {
background-color: red;
flex: 1;
min-width: 250px;
}
.grid-container {
flex: 4;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
.grid-item {
border: 1px solid black;
padding: 20px;
font-size: 24px;
text-align: center;
overflow: hidden;
}
#flex-container {
display: flex;
flex-direction: row;
min-height: 100vh;
}
</style>
</head>
<body>
<div id="flex-container">
<aside class="sidebar">
</aside>
<section class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">6</div>
<div class="grid-item">7</div>
<div class="grid-item">8</div>
<div class="grid-item">9</div>
<div class="grid-item">10</div>
<div class="grid-item">11</div>
<div class="grid-item">12</div>
<div class="grid-item">13</div>
<div class="grid-item">14</div>
<div class="grid-item">15</div>
<div class="grid-item">16</div>
<div class="grid-item">17</div>
<div class="grid-item">18</div>
</section>
<div id="page-buttons">
prev
next
</div>
</div>
Checkout the following Code.
#main{
display :flex;
}
#sidebar{
width:70px;
height: 300px;
border: solid black 1px;
}
#grid-area{
width:200px;
height: 300px;
border: solid black 1px;
display: block;
}
#grid{
width:200px;
height: 250px;
border: solid black 1px;
display: block;
}
<div id="main">
<div id="sidebar"></div>
<div id="grid-area">
<div id="grid"></div>
<div id="button">next / prev</div>
</div>
</div>
You should use nested flex containers. Section and bottom div should be wrapped inside another flex container with flex direction to column.
So outer flex will make sidebar & inner flex container to be side by side.
Or just use a normal div container instead of flex.
here is another example only with grid keeping the pre/next button at the bottom of the viewport:
body {
margin: 0;
}
#grid-container {
display: grid;
height: 100vh;
grid-template-columns: minmax(250px, 1fr) 4fr;
grid-template-rows: 1fr auto;
}
aside {
background-color: red;
border: 1px solid;
margin: 0.25em;
grid-row: span 2;
grid-column: 1;
}
section,
#page-buttons {
grid-column: 2;
border: solid 1px;
margin: 0.25em;
}
section {
overflow: auto;
}
#page-buttons {
display: flex;
gap: 1em;
padding: 0.5em;
background: lightgray;
justify-content: center;
}
.grid-item {
border: 1px solid black;
padding: 20px;
font-size: 24px;
text-align: center;
overflow: hidden;
}
<div id="grid-container">
<aside class="sidebar">
</aside>
<section class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">6</div>
<div class="grid-item">7</div>
<div class="grid-item">8</div>
<div class="grid-item">9</div>
<div class="grid-item">10</div>
<div class="grid-item">11</div>
<div class="grid-item">12</div>
<div class="grid-item">13</div>
<div class="grid-item">14</div>
<div class="grid-item">15</div>
<div class="grid-item">16</div>
<div class="grid-item">17</div>
<div class="grid-item">18</div>
</section>
<div id="page-buttons">
prev
next
</div>
</div>
I hope someone can help me to end my 16 hour search. I have to make
six responsive squares in a 2 x 3 raster.
Inside the square there has to be a responsive circle.
Inside the circle there has to be a centered letter.
I have to use Flexbox.
I am not allowed to use Grid and/or tables.
The squares and circles need to keep their aspect ratio and must fill the container.
CSS-only
div {
display: flex;
flex: 1;
justify-content: space-between;
font-size: 10rem;
}
.blokrij {
flex-direction: column;
width: 50%;
}
.vierkant {
background-color: hsla(26, 100%, 50%, 1.00);
flex: 1 1 auto;
max-width: 100%;
border-radius: 10%;
margin 1px;
}
.rond {
background-color: blue;
border-radius: 50%;
}
<div class="container">
<div class="blokrij">
<div class="vierkant">
<div class="rond"></div>L</div>
<div class="vierkant">
<div class="rond"></div>O</div>
<div class="vierkant">
<div class="rond"></div>I</div>
</div>
<div class="blokrij">
<div class="vierkant">
<div class="rond"></div>L</div>
<div class="vierkant">
<div class="rond"></div>O</div>
<div class="vierkant">
<div class="rond"></div>I</div>
</div>
</div>
I'm so frustrated I cant figure out what the hell I have to do. Especially because I know how to fix it with GRID.
Thansk for helping in Advance!
It is better to assign different codes to their own sections
The text is not written inside the circle
The ratios are not set correctly
Sizes are not set correctly
I set margin: 10px; and padding: 10px; for better and more clarity.
You might say that circles are not precise and are more like ellipses
This is true because they are measured relative to the screen
They may have different sizes in different sizes
.container{
width:100%;
height: 100vh;
display: flex;
}
.blokrij {
display: flex;
flex-direction: column;
width: 50%;
height: 100%;
}
.vierkant {
background-color: hsla(26, 100%, 50%, 1.00);
border-radius: 10%;
margin 1px;
height: 100%;
margin: 10px;
padding: 10px;
}
.rond {
height: 100%;
background-color: blue;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 10rem;
}
<div class="container">
<div class="blokrij">
<div class="vierkant">
<div class="rond">L</div>
</div>
<div class="vierkant">
<div class="rond">O</div>
</div>
<div class="vierkant">
<div class="rond">I</div>
</div>
</div>
<div class="blokrij">
<div class="vierkant">
<div class="rond">L</div>
</div>
<div class="vierkant">
<div class="rond">O</div>
</div>
<div class="vierkant">
<div class="rond">I</div>
</div>
</div>
</div>
If you want the circles and squares to be exactly the exact circle and square, you can measure exactly with px , rem, ...
For example:
.container{
width:400px;
height: 400px;
display: flex;
}
.blokrij {
display: flex;
flex-direction: column;
width: 50%;
height: 100%;
}
.vierkant {
background-color: hsla(26, 100%, 50%, 1.00);
border-radius: 10%;
margin 1px;
height: 100%;
margin: 5px;
padding: 5px;
}
.rond {
height: 100%;
background-color: blue;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 10rem;
}
<div class="container">
<div class="blokrij">
<div class="vierkant">
<div class="rond">L</div>
</div>
<div class="vierkant">
<div class="rond">O</div>
</div>
<div class="vierkant">
<div class="rond">I</div>
</div>
</div>
<div class="blokrij">
<div class="vierkant">
<div class="rond">L</div>
</div>
<div class="vierkant">
<div class="rond">O</div>
</div>
<div class="vierkant">
<div class="rond">I</div>
</div>
</div>
</div>
You have to give the circles a dedicated width and height, put the letters inside them and define for all flex-items the centering with justify-content and align-items. For the responsiveness you should define width and height of the circle and the font-size with the same responsive dimension, for example vw. The width for the columns isn't necessary.
Working example:
div {
display: inline-flex;
flex: 1;
justify-content: center;
align-items: center;
font-size: 10vw;
}
.blokrij {
flex-direction: column;
}
.vierkant {
background-color:hsla(26,100%,50%,1.00);
border-radius: 10%;
margin: 1px;
}
.rond {
width: 20vw;
height: 20vw;
background-color: blue;
border-radius: 50%;
}
<div class="container">
<div class="blokrij">
<div class="vierkant">
<div class="rond">L</div>
</div>
<div class="vierkant">
<div class="rond">O</div>
</div>
<div class="vierkant">
<div class="rond">I</div>
</div>
</div>
<div class="blokrij">
<div class="vierkant">
<div class="rond">L</div>
</div>
<div class="vierkant">
<div class="rond">O</div>
</div>
<div class="vierkant">
<div class="rond">I</div>
</div>
</div>
</div>
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/
I have a dummy screen with background image. The background image correctly expands or contracts with the size of the viewport. I have dummy flexbox content that I intentionally make overflow the bottom of the page.
The scrollbar correctly appears, but it will not scroll far enough to show all the content that overflowed.
Apologies: the content is varied so I can tell what IS NOT showing.
Dummy header menu bar is fine.. it is supposed to scroll up - and it does.
CSS:
html {
box-sizing: border-box;
}
body {
box-sizing: border-box;
overflow-y: auto;
min-height: 100vh;
width: 100%;
margin: 0; padding: 0; border: 0; cursor: default
}
ul {
list-style: none;
li {
display: inline;
margin-left: 50px;
margin-top: 50px;
}
}
.blockStyleEven {
display: flex;
flex-direction: row;
color: white;
justify-content: space-evenly;
}
.blockSpaceAround {
display: flex;
flex-direction: row;
color: white;
justify-content: space-around;
}
.blockSpaceBetween {
display: flex;
flex-direction: row;
color: white;
justify-content: space-between;
}
.blockStart {
display: flex;
flex-direction: row;
color: white;
justify-content: flex-start;
}
.blockEnd {
display: flex;
flex-direction: row;
color: white;
justify-content: flex-end;
}
.blockCenter {
display: flex;
flex-direction: row;
color: white;
justify-content: center;
}
.maroon {
width: 100px;
height: 100px;
background-color: maroon;
}
.red {
width: 100px;
height: 100px;
background-color: red;
}
.green {
width: 100px;
height: 100px;
background-color: green;
}
.blue {
width: 100px;
height: 100px;
background-color: blue;
}
.workspace {
background: url("././Features.jpg") no-repeat center center fixed;
background-size: cover;
height: 100vh;
width: 100vw;
overflow: hidden;
h1 {
color: #E0B228;
}
h2 {
color: #2856E0;
}
}
HTML:
<div [ngStyle]="{'width': '100vw', 'height': '100vh'}">
<div [ngStyle]="{'display': 'flex', 'flex-direction': 'column'}">
<div [ngStyle]="{'background-color': 'beige'}">
<ul>
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
</div>
<div class="workspace">
<div class="blockStyleEven">
<div class="maroon">space-evenly</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockSpaceAround">
<div class="maroon">space-around</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockSpaceBetween">
<div class="maroon">space-between</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockStart">
<div class="maroon">start</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockEnd">
<div class="maroon">end</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockCenter">
<div class="maroon">center</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockStyleEven">
<div class="maroon">space-evenly</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockSpaceAround">
<div class="maroon">space-around</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockSpaceBetween">
<div class="maroon">space-between</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockStart">
<div class="maroon">start</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockEnd">
<div class="maroon">end</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
<div class="blockCenter">
<div class="maroon">center</div>
<div class="red">RED</div>
<div class="green">GREEN</div>
<div class="blue">BLUE</div>
</div>
</div>
</div>
</div>
Thanks in advance.
Yogi
Finally figured it out. The problem was the scrollbar was "too short" to show all the content. This was because my workspace class was on a div below the dummy menu bar. When I put the workspace (containing Margin: auto) on the outer move div, it worked perfectly.
Thanks for all your help.
Apologies for the earlier poor formatting, which has now been cleaned up.
Yogi