Use of Flexbox and avoid justification - html

I have a problem with this flexbox. I would like to place 3 div per row. For this reason I've used flexbox.
The first 3 divs are fine and have 33% width, while the divs 4 and 5 get 50%.
Is there any trick to do the job?
Thanks
* {
box-sizing: border-box;
}
.flex-container {
display: flex;
flex-wrap: wrap;
font-size: 30px;
text-align: center;
}
.flex-item-left {
background-color: #f1f1f1;
padding: 10px;
flex: 33%;
}
.flex-item-center {
background-color: dodgerblue;
padding: 10px;
flex: 33%;
}
.flex-item-right {
background-color: red;
padding: 10px;
flex: 33%;
}
/* Responsive layout - makes a one column-layout instead of a two-column layout */
#media (max-width: 800px) {
.flex-item-right, .flex-item-left {
flex: 100%;
}
}
<h1>Responsive Flexbox</h1>
<p>In this example, we change the percentage of flex to create different layouts for different screen sizes.</p>
<p><b>Resize the browser window to see that the direction changes when the
screen size is 800px or smaller.</b></p>
<div class="flex-container">
<div class="flex-item-left">1</div>
<div class="flex-item-center">2</div>
<div class="flex-item-right">3</div>
</div>
<div class="flex-container">
<div class="flex-item-left">4</div>
<div class="flex-item-center">5</div>
</div>

flex: 33% is short for flex: 1 1 33% meaning that the container will grow or shrink if needed with a basis of 33%. Since there is space left, the containers will grow to 50%.
To fix this, replace the flex property with 0 1 33% meaning that it cannot grow and will not be larger than 33%.

You can simplify with display: grid; and it will give you a little more control over your layout.
* {
box-sizing: border-box;
}
.row-1 {
grid-column: 1 / -1;
grid-gap: 0;
display: grid;
grid-template-columns: repeat(3, 1fr);
flex-direction: column;
text-align: center;
}
.row-2 {
grid-column: 1 / -1;
grid-gap: 0;
display: grid;
grid-template-columns: repeat(2, 50%);
flex-direction: column;
text-align: center;
}
.flex-container {
display: flex;
flex-wrap: wrap;
font-size: 30px;
text-align: center;
}
.flex-item-left {
background-color: #f1f1f1;
padding: 10px;
}
.flex-item-center {
background-color: dodgerblue;
padding: 10px;
}
.flex-item-right {
background-color: red;
padding: 10px;
}
/* Responsive layout - makes a one column-layout instead of a two-column layout */
#media (max-width: 800px) {
.row-1, .row-2 {
display: flex;
flex-direction: column;
}
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no" />
</head>
<body>
<h1>Responsive Flexbox</h1>
<p>In this example, we change the percentage of flex to create different layouts for different screen sizes.</p>
<p><b>Resize the browser window to see that the direction changes when the
screen size is 800px or smaller.</b></p>
<div class="row-1">
<div class="flex-item-left">1</div>
<div class="flex-item-center">2</div>
<div class="flex-item-right">3</div>
</div>
<div class="row-2">
<div class="flex-item-left">4</div>
<div class="flex-item-center">5</div>
</div>
</body>
</html>

Related

Issues adding a gap between two aligned items [duplicate]

This question already has answers here:
Better way to set distance between flexbox items
(40 answers)
Closed 1 year ago.
As shown in the code snippet below i have created two buttons that are always the same width, but im unable to make a gap between them.
Same goes for the mediaquery version (mobile)
How can i do it?
.flex-container {
display: flex;
justify-content: center;
margin: 1em;
}
.flex-container .flex-container {
display: grid;
grid-template-columns: 1fr 1fr;
}
.flex-item {
height: 1.7rem;
padding: 0 1.2rem;
width: 100%;
}
.item1{
margin-right:1vw; /*wont work*/
}
#media only screen and (max-width: 480px) {
.flex-container .flex-container{
display:flex;
flex-direction: column;
}
}
<div class="flex-container">
<div class="flex-container">
<button class="flex-item item1">Button1</button>
<button class="flex-item">Button2 really long with same width</button>
</div>
</div>
column-gap: 1vw; works as expected:
.flex-container {
display: flex;
justify-content: center;
margin: 1em;
column-gap: 1vw;
}
.flex-container .flex-container {
display: grid;
grid-template-columns: 1fr 1fr;
}
.flex-item {
height: 1.7rem;
padding: 0 1.2rem;
width: 100%;
}
#media only screen and (max-width: 480px) {
.flex-container .flex-container {
display: flex;
flex-direction: column;
}
}
<div class="flex-container">
<div class="flex-container">
<button class="flex-item item1">Button1</button>
<button class="flex-item">Button2 really long with same width</button>
</div>
</div>

Shrink grid container to number of rows

I have a flexbox with a grid and a div in it, and I'd like to collapse the grid container's height to the height of the rows, so that the buttons below it are just below the grid items. The number of rows is also dynamic, because I'm using grid-template-columns: repeat(auto-fit, minmax(250px, 1fr). I can set a max-height of the grid items, like in this image, but that only makes the items smaller and doesn't make the grid container any shorter.
I've tried changing the flexbox they're in so the flex-direction is row, and set flex-wrap to wrap, but that causes other problems and overlapping text when the window size changes. Setting the height or max-height of the grid container to fit-content seems to do nothing as well.
Here is what I have:
<!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 rgba(0, 0, 0, 0.8);
padding: 20px;
font-size: 24px;
text-align: center;
overflow: hidden;
min-height: 100px;
}
#main-container {
display: flex;
flex-direction: row;
min-height: 100vh;
}
#section-container {
display: flex;
flex-direction: column;
width: 100%;
}
#page-buttons {
height: 50px;
text-align: center;
font-size: 20px;
}
</style>
</head>
<body>
<div id="main-container">
<aside class="sidebar">
</aside>
<div id="section-container">
<section class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
</section>
<div id="page-buttons">
first
prev
page
next
last
</div>
</div>
</div>
</body>
</html>
The style
.grid-container {
flex: 4;
}
is equivalent to flex-grow: 4;
so it makes the container grow. Just remove it and it will keep its dimension
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 rgba(0, 0, 0, 0.8);
padding: 20px;
font-size: 24px;
text-align: center;
overflow: hidden;
min-height: 100px;
}
#main-container {
display: flex;
flex-direction: row;
min-height: 100vh;
}
#section-container {
display: flex;
flex-direction: column;
width: 100%;
}
#page-buttons {
height: 50px;
text-align: center;
font-size: 20px;
}
<body>
<div id="main-container">
<aside class="sidebar">
</aside>
<div id="section-container">
<section class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
</section>
<div id="page-buttons">
first
prev
page
next
last
</div>
</div>
</div>
</body>

CSS values for DIV structure setup

I need to setup the following DIV structure (See image below. It tells more than a 1000 words)
The structure consists of 2 colums. The main column (left) has a variable width and 100% height.
The right colums has a FIXED width of 380px and 100% height.
Then inside the right column I need 3 DIVS.
The top DIV has a fixed height of 200px and must be aligned to the top.
The bottom DIV has a fixed height of 150px and must be aligned to the bottom.
The middle DIV has a variable height and must fill up the space vertically.
This is the DIV setup And the CSS I have:
.main-content {
width: 100%;
padding: 0px;
}
.col-1 {
width: calc(100% - 380px);
min-height: calc(var(--vh, 1vh)*100);
background-color: #2693FF;
float: left;
}
.col-2 {
width: 380px;
min-height: calc(var(--vh, 1vh)*100);
float: right;
}
.col-2-top {
height: 200px;
background-color: #00B200;
}
.col-2-middle {
height: 100%;
background-color: #FF8000;
}
.col-2-bottom {
height: 100px;
background-color: #B25900;
}
<div class="main-content">
<div class="col-1"></div>
<div class="col-2">
<div class="col-2-top"></div>
<div class="col-2-middle"></div>
<div class="col-2-bottom"></div>
</div>
</div>
Then... Column 1 and 2 should stack when the viewport width becomes less than 768px.
Column 1 on top and Column 2 below it.
Like this:
I think I'm almost there, but I'm having problems with the height of the Main DIV and the heights and aligning of the DIV col-2 middle DIV. I also need a bit helpt to get these divs stack nicely above each each other.
I would suggest that you use grid layout instead of floating around your <div>s, grid layout allows you to structure your layout and separate them in columns and rows, and areas using grid-template-areas.
for max-width:748 just add media query, here is how it might be implemented:
body {
padding: 0;
margin: 0;
}
.main-content {
display: grid;
background-color: #2196F3;
grid-template-areas:
'main fixed-top'
'main variable-mid-area'
'main fixed-bottom';
background-color: #2196F3;
height: 100vh;
grid-template-columns: 1fr 380px;
grid-template-rows: 200px 1fr 150px;
}
.main-content > div {
color: #fff;
font-size: 30px;
vertical-align: middle;
display: flex;
justify-content: center;
align-items: center;
}
.main {
grid-area: main;
background-color: #2693FC;
}
.variable-mid-area {
grid-area: variable-mid-area;
background-color: #FF8015;
}
.fixed-top {
grid-area: fixed-top;
background-color:#00B21F;
}
.fixed-bottom {
grid-area: fixed-bottom;
background-color: #B2590B;
}
#media only screen and (max-width: 768px) {
.main-content {
grid-template-areas:
'main'
'fixed-top'
'variable-mid-area'
'fixed-bottom';
grid-template-rows: 300px 200px 1fr 150px;
grid-template-columns: 100%;
height: auto;
}
}
<div class="main-content">
<div class="main"> main </div>
<div class="fixed-top"> 200 </div>
<div class="variable-mid-area"> auto </div>
<div class="fixed-bottom"> 150 </div>
</div>
If you have any questions how the css works, feel free to ask them in the comments.
I know the background-colors are irrelevant but they help to visualize it.
.container {
min-width: 768px;
width: 100%;
display: grid;
grid-template-columns: calc(100% - 380px) 1fr;
min-height: 100vh;
}
.col1 {
background-color: dodgerblue;
}
.col2 {
display: flex;
flex-direction: column;
}
.col2-row1 {
height: 200px;
background-color: orange;
}
.col2-row2 {
background-color: forestgreen;
height: 100%;
}
.col2-row3 {
height: 150px;
background-color: red;
}
#media (max-width: 768px) {
.container {
grid-template-columns: 1fr;
}
}
<div class="container">
<div class="col1">1</div>
<div class="col2">
<div class="col2-row1">2</div>
<div class="col2-row2">3</div>
<div class="col2-row3">4</div>
</div>
</div>

Make side bars reducing with max-width by degrees

How to make side parts of web page reduce they width with reducing width of whole page by degrees?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.container {
display: grid;
grid-template-columns: 10% 80% 10%;
min-height: 100vh;
}
.side-right {
background: red;
}
.side-left {
background: blue;
}
.main {
background: green;
}
#media screen and (max-width: 1000px) {
.container {
grid-template-columns: 0 100% 0;
}
}
</style>
</head>
<body>
<div class="container">
<div class="side-right">
</div>
<div class="main">
</div>
<div class="side-left">
</div>
</div>
</body>
</html>
In example below after max-width = 1000px side elements are dissapearing instantly, but I want to make them reducing they width reacting by every pixel changed on max-width. How to make it?
If I understand your requirement correctly...change the initial grid-template-columns to
grid-template-columns: 1fr minmax(1000px, 8fr) 1fr;
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
::before,
::after {
box-sizing: inherit;
}
.container {
display: grid;
grid-template-columns: 1fr minmax(1000px, 8fr) 1fr;
min-height: 100vh;
}
.side-right {
background: red;
}
.side-left {
background: blue;
}
.main {
background: green;
}
#media screen and (max-width: 1000px) {
.container {
grid-template-columns: 0 1fr 0;
}
}
<div class="container">
<div class="side-right">
</div>
<div class="main">
</div>
<div class="side-left">
</div>
</div>
You can animate all with flex-box and just by changing some of your css.
.container {
display: flex;
min-height: 100vh;
flex-direction: row-reverse;
}
.side-right {
background: red;
width: 100%;
}
.side-left {
background: blue;
width: 100%;
}
.main {
background: green;
min-width: 600px;
}
Thats just a basic example. Consider reading more about flex-box.
Try to add min-with: 50px; to .side-right and .side-left
And then give them both an z-index: 1;
So they wont lay under your main
Hope that helps

Can I reorder using CSS / HTML or do I need JavaScript?

I am working on a webpage which has a sidebar and a main section. The CSS / HTML essentially look like this:
<html><head>
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<style>
#sidebar {
float: right;
min-width: 220px;
height: 200px;
background-color: Red;
}
#content {
background-color: #f0f0f0;
height: 200px;
overflow: hidden;
}
#media screen and (max-width: 450px) {
#sidebar {
float: none;
}
}
</style></head>
<body>
<div>
<div id="sidebar">
</div>
<div id="content">
</div>
</div>
</body></html>
So the idea is that when displayed side-by-side, the content div takes up the width of the window not used by the sidebar, but when we move to mobile sized screens the sidebar div stops floating and moves inline.
This is fine for the desktop site, but on the mobile site, because I have put my sidebar div before my main div, the sidebar appears first, and I want it to appear below.
Is there an easy / generally practised solution to this that doesn't involve using javascript to move the divs around after load? Should I be taking a different approach?
Yes, you can. There are two ways you can go about it:
Legacy solution
Put your sidebar after your content and float:right your main content container on desktop size. This way the sidebar will be on the left on desktop but displayed after the main content on mobile.
body {margin: 0;}
.main-wrapper >*{
box-sizing: border-box;
padding: 20px;
display: inline-block;
min-height: 200px;
}
#sidebar {
background-color: Red;
min-width: 30%;
max-width: 30%;
min-height: 200px;
}
#content {
background-color: #999;
float: right;
width: 70%;
}
#media screen and (max-width: 450px) {
#content,#sidebar {
float: none;
width: 100%;
min-width: initial;
max-width: initial;
}
}
<div class="main-wrapper">
<div id="content">
content
</div>
<div id="sidebar">
sidebar
</div>
</div>
Modern solution
Use order (flexbox).
body {margin: 0;}
.main-wrapper {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-flex-wrap: nowrap;
-ms-flex-wrap: nowrap;
flex-wrap: nowrap;
-webkit-box-align: stretch;
-webkit-align-items: stretch;
-ms-flex-align: stretch;
align-items: stretch;
min-height: 100vh;
}
#sidebar, #content {
padding: 20px;
box-sizing: border-box;
}
#sidebar {
background-color: red;
-webkit-box-flex: 0;
-webkit-flex: 0 0 30%;
-ms-flex: 0 0 30%;
flex: 0 0 30%;
}
#content {
-webkit-box-flex: 1;
-webkit-flex: 1 0 auto;
-ms-flex: 1 0 auto;
flex: 1 0 auto;
}
#media (max-width: 450px) {
.main-wrapper{
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
#sidebar, #content {
-webkit-box-flex: 1;
-webkit-flex: 1 0 100%;
-ms-flex: 1 0 100%;
flex: 1 0 100%;
}
#sidebar {
-webkit-box-ordinal-group: 2;
-webkit-order: 1;
-ms-flex-order: 1;
order: 1;
}
}
<div class="main-wrapper">
<div id="sidebar">
sidebar
</div>
<div id="content">
content
</div>
</div>
For this, if you want to make the development easier and with limited use of JavaScript I recommend you take a look at the Bootstrap framework. This implements a new and intuitive class system that allows for dynamic scaling through CSS classes in your HTML instead of JavaScript.
Take a look, it's becoming pretty standard for many webpages and what you want should be pretty easy to do with the framework.
Hope this helps:)