Container not taking all the space in the page - html

I have started web dev not that long ago, and today I really tried to understand the basics of css and html, and I've got almost everything to work correctly. But I'm facing a problem that I can't seem to be able to solve by myself.
So here I am. I'm trying to replicate this design I did on figma, as a challenge for myself, and as a huge fan of Family Guy :
See the image here
So I started by learning how to create a css grid (I thought it was going to be usefull for each part of the page), then how to create a side bar and all of that. But there I am stuck :
My whole page is cranked into a tiny part :
This
For further investigation, here's the grid in inspect mode :
This
So how can I make it take the whole page like it should :
Here's my html and css
HTML
<!DOCTYPE html>
<head>
<title>FamilyGuy</title>
<link rel="stylesheet" type="text/css" href="./assets/css/styles.css">
</head>
<body>
<div class="container">
<div class="navbar">
</div>
<div class="card-1">
<div class="card-image-container">
<img class="card-image" src="./assets/img/Family_Guy_Season1.png">
</div>
<div class="card-title-container">
<h3 class="card-title">Episode 1</h3>
</div>
</div>
<div class="card-2">
<div class="card-image-container">
<img class="card-image" src="./assets/img/Family_Guy_Season1.png">
</div>
<div class="card-title-container">
<h3 class="card-title">Episode 2</h3>
</div>
</div>
</body>
</html>
CSS
html {
display: block;
margin: 0;
padding: 0;
}
body {
background: #1E1E1E;
font-family: 'Inter', sans-serif;
border: 0;
margin: 0;
padding: 0;
}
.container {
display: grid;
max-width: 1920px;
max-height: 1080px;
grid-template-columns: [first] 18.23% [second] 2.6% [third] auto [fourth] 2.6% [fifth] auto [sixth] 2.6% [seventh] auto [eighth] 2.6% [ninth] auto [tenth] 2.6% [eleventh] 42.19%;
grid-template-rows: [first] 2.78% [second] 2.78% [third] 5.28% [fourth] 13.89% [five] 3.06% [sixth] 19.44% [seventh] 2.6% [ninth] 19.44% [tenth] 2.6% [eleventh] 19.44% [twelveth] 2.6%;
}
div.navbar {
background: #2F3136;
max-width: 350px;
max-height: 1080px;
grid-column-start: first;
grid-column-end: span second;
grid-row-start: first;
grid-row-end: span twelveth;
}
div.card-1 {
position: inherit;
background: #2F3136;
max-width: 140px;
max-height: 210px;
grid-column-start: third;
grid-column-end: span fourth;
grid-row-start: sixth;
grid-row-end: seventh;
border-radius: 7.14%;
}
div.card-2 {
position: inherit;
background: #2F3136;
max-width: 140px;
max-height: 210px;
grid-column-start: fifth;
grid-column-end: span sixth;
grid-row-start: sixth;
grid-row-end: seventh;
border-radius: 7.14%;
}
div.card-image-container {
display: flex;
justify-content: center;
position: relative;
max-width: 120px;
max-height: 158.68px;
border-radius: 7.14%;
padding: 7.14%;
border-radius: 7.14%;
width: 85.71%;
height: 75.56%;
}
img.card-image {
display: flex;
border-radius: 7.14%;
justify-content: center;
}
div.card-title-container {
display: flex;
justify-content: center;
align-items: center;
position: relative;
max-width: 140px;
max-height: 41px;
}
h3.card-title {
display: flex;
margin-bottom: 0;
margin-top: .2em;
margin-left: 0;
margin-right: 0;
}
h3 {
font-size: 1rem;
color: #FFFFFF;
font-weight: 500;
}
Please keep in mind that I just started static web dev recently, and that there may be a lot of errors in my code. I already apologize for the possible big noob error I could have done. This is actually my first time really trying to do something without any template or base code, so yeah, I'm kinda going blindfolded into this challenge. Already thanks for the help !
As stated. I've tried to replicate my figma design, but my body/html won't spread all the way on the page.
UPDATE : looks like using :
<div class="container" style="height: 852px">
In the HTML, fixed my problem. Alhough, I'm not entirely satisfied of this, as it creates a scroll bar on the right. Which I'm not particularly a fan of. If any of you has ideas, I would gladly appreciate it.

There are two major problems with your code, apart from your issue:
The page is constructed as one large grid. Espescially CSS Grid can be very intimidating creating such grid, where Flexbox Layout will probably feel more intuitive.
From your image it is clear that you have designed a main page with three main sub panels, each with its own distinct function. Tools, Navigation & Image Grid and Preview.
Each sub panel can be divided into several child panels and in some cases ever deeper nested panels.
Fixed units like px are your enemy, particularly when you want to design a responsive web page that can fit on various devices. Percentages based on a fixed value, while relative, will still eventually result in fixed values, e.g. 10% of 1920px will always be 192px. This will likely lead to cascading element size and positioning issues.
Instead of helping you with an issue in code you most likely will want to change one way or another, I took the liberty of creating a responsive base framework you can extend and modify to your needs:
I divided your design into the nested panels mentioned before and removed all fixed units, except for a few in the media queries.
Introduced a few Flexbox Layout shortcut (one letter) attribute selectors for easy 'on-the-fly' flexbox use.
Element font sizes defined as parent dependent (em unit).
Element sizes and spacing as root dependent (rem unit).
Comments are in the CSS where applicable.
Downloadable version of the code at Codepen.
There is still a lot to do, I didn't create the entire page for you, but maybe this will give you a head start...
Snippet
/* * { outline: 1px dashed white }/* for debugging only */
/********************************/
/* some convenient global rules */
/********************************/
* { box-sizing: border-box }
html, body { width: 100%; max-width: 100% }
body { min-height: 100vh; margin: 0 }
/* Linear equation y=mx+b using points p1(320,12) p2(1280,18) */
body { font-size: calc(0.625vmin + 0.625rem) } /* responsive page font */
img {
display: block; /* removes whitespace below image */
object-fit: cover; /* fill, but clip when lack of room */
width: 100%; /* width is leading */
height: 100%;
}
iframe { border: none; max-width: 100% }
/* this and thats */
.icon { display: inline-grid; place-items: center; padding: 0.25rem }
.big { font-size: 1.75em; font-weight: bolder }
.small { font-size: 0.75em }
/* Easy flexbox shorcuts for on-the-fly use */
[F] { display: flex; flex-wrap: wrap }
[R] { flex-direction: row } /* flexbox default */
[C] { flex-direction: column }
[N] { flex-wrap: nowrap } /* Flexbox default */
[F] > * { flex: 1 } /* allow flexbox kids to grow */
body {
background-color: #1e1e1e; color: White;
font-family: 'Inter', sans-serif;
line-height: 1.5;
}
header, footer, nav {
display: flex; align-items: center;
width: 100%;
padding: 0.5rem 0;
font-weight: bold;
}
header { font-size: 1.5rem; justify-content: center }
footer { font-size: 0.8rem; justify-content: end }
/***************/
/* end globals */
/***************/
/**********************/
/* Main app container */
/**********************/
.main {
display: flex; flex-wrap: wrap;
width: 100%; min-height: 100vh; /* fill parent */
background-color: #2f3136;
}
/******************/
/* All sub panels */
/******************/
.sub {
/* Flexbox column (of rows) container */
display: flex; flex-flow: column wrap;
gap: 1rem; /* generic gap between various content panels */
/* this will make a panel fit snuggly in a 320px or 360px device */
min-width: min(18rem, 100%); /* = 288/16 or 100% */
padding: 0.5rem 2rem;
}
.sub footer { margin-top: auto } /* move to bottom */
/* Footers are here to show height of panels */
/* panel spacing ratio 1:2:2 (comparable to grid 'fr' unit) */
/* when available and respecting .sub min-width */
.sub.tools { flex: 1 } /* allow to grow, where */
.sub.episodes { flex: 2 } /* flex-shrink = 1 and */
.sub.preview { flex: 2 } /* flex-basis = 0% */
/*******************/
/* Sub tools panel */
/*******************/
.search label { width: 100%; }
.search .icon { font-size: 1.5em }
.search input { font-size: 1em; width: calc(100% - 1.5em - 0.5rem) }
/* 100% minus icon size minus L/R icon padding */
/**********************/
/* Sub episodes panel */
/**********************/
.sub.episodes {
/* Define custom property for numer of image columns */
--img-columns: 2; /* mobile first: 2 columns only */
/* Overridden by Media Queries */
background-color: #36393f;
}
.navigation { font-size: 1.75em }
/* Default for small devices < 720px */
.episode-grid {
/* Use column value set by Media Queries */
display: grid; grid-template-columns: repeat(var(--img-columns), 1fr);
gap: 0.5rem;
}
/* Media queries for gradually bigger devices, change as required */
/* Common use */
/*#media screen and (min-width: 721px) { .episode-grid { grid-template-columns: repeat(3, 1fr) } } /* > 720px */
/*#media screen and (min-width: 1081px) { .episode-grid { grid-template-columns: repeat(4, 1fr) } } /* > 1080px */
/*#media screen and (min-width: 1367px) { .episode-grid { grid-template-columns: repeat(5, 1fr) } } /* > 1366px */
/*#media screen and (min-width: 1921px) { .episode-grid { grid-template-columns: repeat(7, 1fr) } } /* > 1920px */
/* Custom property use */
/* Custom properties defined at parent element level, modified and used at element child level */
#media screen and (min-width: 721px) { .episode-grid { --img-columns: 3 } } /* > 720px */
#media screen and (min-width: 1081px) { .episode-grid { --img-columns: 4 } } /* > 1080px */
#media screen and (min-width: 1367px) { .episode-grid { --img-columns: 5 } } /* > 1366px */
#media screen and (min-width: 1921px) { .episode-grid { --img-columns: 7 } } /* > 1920px */
.card .small { text-align: center }
/*********************/
/* Sub preview panel */
/*********************/
.sub.preview .content { gap: 1rem }
.thumblist, .settings {
gap: 0.25rem;
padding: 1rem;
background-color: #36393f;
border-radius: 0.5rem;
}
.thumb {
padding: 0.5rem;
background-color: #2f3136;
}
.card,.thumb { border-radius: 0.5rem; padding: 0.5rem; background-color: #2f3136 }
:is(.card,.thumb) img { border-radius: 0.75rem }
<!-- Main app container -->
<div class="main">
<!-- Tools sub panel -->
<div class="sub tools">
<header>
<div class="logo">
<img src="https://i.imgur.com/gEQ9EK6.png">
</div>
</header>
<div class="search" F C>
<div class="bar">
<label><input placeholder="Search"><span class="icon">ⓘ</span></label>
</div>
<div class="results">
<div class="list" F C>
<div>result one</div>
<div>result two</div>
<div>result three</div>
<div>result four</div>
<div>result five</div>
<div>result six</div>
</div>
<div class="dots">...</div>
</div>
</div>
<div class="more-tools" F C>
<div class="tool one" >tool one</div>
<div class="tool two" >tool two</div>
<div class="tool three">tool three</div>
</div>
<footer>tools</footer>
</div>
<!-- Episodes sub panel -->
<div class="sub episodes">
<header></header>
<div class="page-control" F C>
<nav class="navigation" F>
<div class="option"><span class="icon">ⓘ</span><span class="text">text</span></div>
<div class="option"><span class="icon">ⓘ</span><span class="text">text</span></div>
<div class="option"><span class="icon">ⓘ</span><span class="text">text</span></div>
<div class="option"><span class="icon">ⓘ</span><span class="text">text</span></div>
</nav>
<div class="title">
<div class="big">FamilyGuy.Com</div>
<p class="small">Lorem ipsum dolor sit amet, eos ad wisi eius deserunt, cu iusto nonumes volumus usu, ne aeque aperiam saperet pro. Cu eum laudem sanctus, apeirian torquatos assentior mea ea, eos ut tantas altera sadipscing. Nam splendide voluptatum ad, integre quaeque definitiones mea et.</p>
</div>
</div>
<div class="episode-grid">
<div class="card">
<div F C>
<img src="https://picsum.photos/300/535?random=1">
<div class="small">byline</div>
</div>
</div>
<div class="card">
<div F C>
<img src="https://picsum.photos/300/535?random=2">
<div class="small">byline</div>
</div>
</div>
<div class="card">
<div F C>
<img src="https://picsum.photos/300/535?random=3">
<div class="small">byline</div>
</div>
</div>
<div class="card">
<div F C>
<img src="https://picsum.photos/300/535?random=4">
<div class="small">byline</div>
</div>
</div>
<div class="card">
<div F C>
<img src="https://picsum.photos/300/535?random=5">
<div class="small">byline</div>
</div>
</div>
</div>
<footer>episodes</footer>
</div>
<!-- Movie preview sub panel -->
<div class="sub preview">
<header>Live preview</header>
<div class="content" F C>
<div class="movie">
<iframe src="https://www.youtube.com/embed/N-nJ3EMueyE"
title="Family Guy - Fight with the hologram (Season 21 Episode 6)"
frameborder="0" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen>
</iframe>
</div>
<div>
<div class="episode-selector">Episode selector</div>
</div>
<div class="highlights" F C>
<div>Highlights</div>
<div class="thumblist" F R>
<div class="thumb"><img src="https://picsum.photos/200/112?random=6"></div>
<div class="thumb"><img src="https://picsum.photos/200/112?random=7"></div>
<div class="thumb"><img src="https://picsum.photos/200/112?random=8"></div>
<div class="thumb"><img src="https://picsum.photos/200/112?random=9"></div>
</div>
</div>
<div class="settings" F>
<div class="subtitle" F C>
<p>Available Subtitles</p>
<label class="small">English <input type="checkbox"></label>
<label class="small">French <input type="checkbox"></label>
<label class="small">Spanish <input type="checkbox"></label>
</div>
<div class="audio" F C>
<p>Available Audio tracks</p>
<label class="small">English <input type="checkbox"></label>
<label class="small">French <input type="checkbox"></label>
<label class="small">Spanish <input type="checkbox"></label>
</div>
</div>
</div>
<footer>preview</footer>
</div>
</div>

Related

How to control vertical and horizontal spacing in Flex with horizontal center alignment and wrapping items?

Wrapping items are positioned horizontally and center aligned. How would you control the vertical and horizontal spacing?
In this example, we'd like to have 16px horizontal space between items and 8px vertical space.
Here is a possible solution:
/* Solution */
.flex-wrapper {
padding-top: 1px;
}
.flex-wrapper:before {
content: "";
display: block;
margin-top: -9px;
}
.flex {
display: flex;
flex-wrap: wrap;
margin-left: -16px;
justify-content: center;
}
.flex-item {
padding-left: 16px;
padding-top: 8px;
}
/* For demo purposes, not related to solution. */
body {
margin: 50px;
}
.container {
width: 600px;
outline: 1px solid black;
}
button {
width: 100px;
height: 40px;
background: none;
border: 4px solid red;
font-size: 16px;
}
<div class="container">
<div class="flex-wrapper">
<div class="flex">
<div class="flex-item">
<button>1</button>
</div>
<div class="flex-item">
<button>2</button>
</div>
<div class="flex-item">
<button>3</button>
</div>
<div class="flex-item">
<button>4</button>
</div>
<div class="flex-item">
<button>5</button>
</div>
<div class="flex-item">
<button>6</button>
</div>
<div class="flex-item">
<button>7</button>
</div>
<div class="flex-item">
<button>8</button>
</div>
<div class="flex-item">
<button>9</button>
</div>
</div>
</div>
</div>
This solution feels somewhat hacky, especially the .flex-wrapper part.
Is there a better way?
Notes:
Items can have various widths.
I'm looking for a solution that works regardless of whether the items wrap or not. Items can also span across many lines, not just 2 lines like in this example.
At the time of writing this question, browsers don't have a great support for gap in Flex.
This question shows how to horizontally center align the items, but it doesn't demonstrate how to control the vertical and horizontal space between the items.
Welcome to the wonderful world of CSS-Grid, which is perfect for this.
Way less code and easier to understand as you can see below.
Control of the space between columns and rows is done by grid-column-gap for the gap between - you guessed it - columns and grid-row-gap for the gap between rows.
You could write this even easier, use a repeat function for the columns for example:
grid-template-columns: repeat(5, 100px);
Pretty amazing.
Definetly look into what else you can do with CSS-Grid and forget about Flexbox. This is the future. To get you started check: https://www.w3schools.com/css/css_grid.asp
.container {
display: grid;
width: 564px;
grid-template-columns: auto auto auto auto auto;
grid-column-gap: 16px;
grid-row-gap: 8px;
outline: 1px solid black;
}
button {
width: 100px;
height: 40px;
background: none;
border: 4px solid red;
font-size: 16px;
}
<div class='container'>
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<button>5</button>
<button>6</button>
<button>7</button>
<button>8</button>
</div>
Browser-Support for CSS-Grid is pretty solid btw.
Starting with #rx2347's CSS-grid based answer as a baseline, but getting closer to the layout you are actually seeking... If you have a reasonable number of fixed items you want to place you could manually set the position of your elements to where you want by using repeat() to create a much finer grid, and then place your element at specific columns with finer granularity.
There are probably other ways to achieve this on per-row offset / indent basis with CSS-grid. To make it really automatic, for example to handle a large number of items, and/or an arbitrary number of items, I would be tempted to use jQuery scripting, possibly with CSS grid to iterate and set positions. There may be pure CSS and HTML ways to accommodate a more arbitrary number of elements. It really depends on your application.
.container {
display: grid;
width: 800px;
grid-template-columns: repeat(60, 10px);
grid-column-gap: 16px;
grid-row-gap: 8px;
}
#button1 {
grid-column-start: 4;
}
#button2 {
grid-column-start: 8;
}
#button3 {
grid-column-start: 12;
}
#button4 {
grid-column-start: 16;
}
#button5 {
grid-column-start: 20;
}
#button6 {
grid-column-start: 6;
grid-row-start: 2;
}
#button7 {
grid-column-start: 10;
grid-row-start: 2;
}
#button8 {
grid-column-start: 14;
grid-row-start: 2;
}
#button9 {
grid-column-start: 18;
grid-row-start: 2;
}
button {
width: 100px;
height: 40px;
background: none;
border: 4px solid red;
font-size: 16px;
}
<div class='container'>
<button id="button1">1</button>
<button id="button2">2</button>
<button id="button3">3</button>
<button id="button4">4</button>
<button id="button5">5</button>
<button id="button6">6</button>
<button id="button7">7</button>
<button id="button8">8</button>
<button id="button9">9</button>
</div>
A simple solution could be to use box-sizing and then control the vertical and horizontal spacing with padding.
.flex-item {
box-sizing: border-box;
padding: 4px 8px;
}
Or apply it universally:
*, *:before, *:after {
box-sizing: border-box;
}
https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing
You might use margin to set the spacing:
.container {
width: 600px;
border: 1px solid;
}
section {
display: flex;
flex-flow: row wrap;
justify-content: center;
margin: -8px -8px 0;
}
button {
width: 100px;
height: 40px;
margin: 8px 8px 0;
border: 4px solid red;
background: none;
font-size: 16px;
}
<div class="container">
<section>
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<button>5</button>
<button>6</button>
<button>7</button>
<button>8</button>
<button>9</button>
</section>
</div>
You're not controlling space between elements in your question, as you're using padding property, elements are one after another but you're reaching the effect. If you put a background on each you'll notice what i'm trying to explain.
To control space between elements in a flexbox layout (or another) you need to use margin on items, in this case, on items inside the display: flex; element.
I've used calc values due to SCSS variables, here i changed my variable name to 30px.
There's a snippet that reach what you want.
.flexcontainer {
padding: 0 15px;
width: 100%;
border:1px solid black;
}
.flexrow {
display:flex;
flex-flow: row wrap;
/* only horizontal negative margin for beggining and end of the element, as you may not know which element is first on the left or right, it will compensate the padding of container */
margin: 0px calc(30px/2 * -1);
justify-content: space-around;
}
.flexrow.row-5-el > .element {
flex: 0 1 calc(100%/5 - 30px);
max-width: calc(100%/5 - 30px);
/* sets 15px of margin on each side */
margin: calc(30px/2);
/* for testing purposes */
outline: 1px auto green;
}
<div class="flexcontainer">
<div class="flexrow row-5-el">
<div class="element"> Lorem ipsum </div>
<div class="element"> Lorem ipsum </div>
<div class="element"> Lorem ipsum </div>
<div class="element"> Lorem ipsum </div>
<div class="element"> Lorem ipsum </div>
<div class="element"> Lorem ipsum </div>
<div class="element"> Lorem ipsum </div>
<div class="element"> Lorem ipsum </div>
<div class="element"> Lorem ipsum </div>
</div>
</div>
if you want the first item start at the left 0, you only need to delete the container padding.
here's a live example i did some time ago:
https://codepen.io/joelbonetr/pen/gOpPYbR
(without justify-content as the desired effect was keeping wrapped elements aligned to left)

CSS Grid image and column issue in Chrome

In Chrome, my site is breaking on desktop and mobile.
Issues:
The second section isn't displaying the hero image correctly. The image should have two halves that when hovered, join together.
Hero images jump to the top of the page with only half of the image in view.
When I went to inspect the page, I saw the following in the console
[Deprecation] Percentages row tracks and gutters for indefinite height grid containers will be resolved against the intrinsic height instead of being treated as auto and zero respectively
I looked into it and came to find the fix for the said issue was to change percentages in grid-template-rows or grid-auto-rows to auto.
I applied the given fix and the issue still persisted. It only breaks in Google Chrome. The site looks fine in Firefox.
Here's the code.
HTML:
<section class="page">
<div class="details">
<h1>Skyline KPGC110</h1>
<h2>1973</h2>
</div>
<div class="hero">
<a href="./kenmeri.html">
<img class="model-left" src="./images/front-1.png" alt="model">
<img class="model-right" src="./images/front-2.png" alt="model">
</a>
</div>
</section>
<!-- ------------------------------ Seciton 2 ------------------------------ -->
<section class="page about">
<div class="details">
<h1>Skyline PGC10</h1>
<h2>1969</h2>
</div>
<div class="hero">
<a href="./pgc10.html">
<img class="model-left" src="./images/gtr-left.png" alt="chef">
<img class="model-right" src="./images/gtr-right.png" alt="chef">
</a>
</div>
</section>
<!-- ------------------------------ Section 3 ------------------------------ -->
<section class="page reel">
<div class="details">
<h1>Fairlady 240z</h1>
<h2>1973</h2>
</div>
<div class="hero">
<a href="./fairladyz.html">
<img class="model-left" src="./images/240z-left.jpg" alt="model">
<img class="model-right" src="./images/240z-right.jpg" alt="model">
</a>
</div>
</section>
Desktop view:
.page {
display: grid;
grid-template-columns: 5% 1fr 1fr 1fr 5%;
min-height: 90vh;
}
.about,
.reel {
position: absolute;
bottom: 0%;
left: 0%;
width: 100%;
opacity: 0;
pointer-events: none;
}
.hero {
display: flex; /* gets rid of gap between imgs */
align-self: center;
justify-self: center;
height: 500px;
overflow: hidden;
}
.hero a {
display: flex; /* removes seperation created by a tag */
}
.hero img {
height: 500px;
transition: transform 0.3s ease-out;
cursor: pointer;
}
Breakpoint 1(Laptop):
#media screen and (max-width: 1024px) {
.page {
grid-template-columns: 5% 1fr 5%;
grid-template-rows: 2fr 1fr;
align-items: center;
}
.hero {
height: auto;
grid-column: 2;
}
.hero img {
height: 425px;
}
}
Breakpoint 2(Mobile):
#media screen and (max-width: 768px) {
.page {
grid-template-rows: 1fr;
}
.page-1 h3 {
font-size: 1.125rem;
padding-right: 20px;
}
.hero img {
width: auto;
}
.details h2 {
font-size: 28px;
}
}
The link to the repo is here if you want to get a full look at the code.
In your code,
img {
display: block;
width: 100%;
height: 100%;
}
just remove the width: 100% and it will work fine.

Problems building a flexbox grid

I'm trying to build myself a flexbox with the following design:
My html looks like this (and I would like to NOT change this):
<div class="wrapper">
<div class="page-header">Heading</div>
<h3 class="right_1">right_1</h3>
<div class="right_2">right_2</div>
<div class="left">form element</div>
<h3 class="right_3">right_3</h3>
<div class="right_4">right_4</div>
</div>
This is the standard layout of the joomla contact page. I want to change the design though without altering html/php code.
Is that possible using flexbox?
And can I use #media queries to make right_1 - right_4 to move under left on mobile view (< 800px or example)?
I myself cannot get it to work, I always end up with right_1 - right_4 next to each other instead of them stacking to the total height of the left portion.
The layout you want cannot be achieved with flexbox. The reasons are explained here:
Is it possible for flex items to align tightly to the items above them?
However, the layout is relatively simple with CSS Grid.
There are, in fact, multiple methods for building the layout with Grid. I'll use the grid-template-areas property, which allows you to lay out your elements using ASCII art.
.wrapper {
display: grid;
height: 100vh;
grid-template-columns: 1fr 1fr;
grid-template-areas:
" heading heading "
" left_ right1 "
" left_ right2 "
" left_ right3 "
" left_ right4 "
}
.page-header { grid-area: heading; }
.right_1 { grid-area: right1; }
.right_2 { grid-area: right2; }
.right_3 { grid-area: right3; }
.right_4 { grid-area: right4; }
.left { grid-area: left_; } /* "left" is a pre-defined CSS keyword,
so it may not work */
#media ( max-width: 800px ) {
.wrapper {
grid-template-columns: 1fr;
grid-template-areas:
" heading "
" left_ "
" right1 "
" right2 "
" right3 "
" right4 "
}
}
/* non-essential decorative styles */
.page-header { background-color: red; }
.right_1 { background-color: chartreuse; }
.right_2 { background-color: aqua; }
.right_3 { background-color: skyblue; }
.right_4 { background-color: black; color: white; }
.left { background-color: cornsilk; }
body { margin: 0; }
.wrapper > * {
font-weight: bold;
font-size: 1.5em;
border: 1px solid black;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}
<div class="wrapper">
<div class="page-header">Heading</div>
<h3 class="right_1">right_1</h3>
<div class="right_2">right_2</div>
<div class="left">form element</div>
<h3 class="right_3">right_3</h3>
<div class="right_4">right_4</div>
</div>
jsFiddle demo
In essence, here's how it works:
We establish a block-level grid with display: grid.
With grid-template-columns: 1fr 1fr we are telling the grid to create two columns. The fr unit tells the container to consume available space. It's similar to flexbox's flex-grow property. So both columns will share the full width of the container.
The grid-template-areas property allows you to lay out named grid areas (that you have defined) to create a visual representation of your layout using ASCII art.
In the media query for smaller screens, we remove one column and re-order the grid areas.
Browser Support for CSS Grid
Chrome - full support as of March 8, 2017 (version 57)
Firefox - full support as of March 6, 2017 (version 52)
Safari - full support as of March 26, 2017 (version 10.1)
Edge - full support as of October 16, 2017 (version 16)
IE11 - no support for current spec; supports obsolete version
Here's the complete picture: http://caniuse.com/#search=grid
Here is one way to solve that, based on the existing markup and CSS Flexbox.
The left needs to be absolute positioned for desktop view and the page-header need a fixed height.
If you don't want to set a fixed height, you'll need a script that takes care of the height calculation
html, body {
margin: 0;
}
.wrapper {
position: relative;
display: flex;
flex-direction: column;
min-height: 100vh;
}
.wrapper * {
padding: 0 10px;
margin: 0;
border: 1px solid black;
box-sizing: border-box;
}
.page-header {
height: 70px;
width: 100%;
background: red;
}
.right_1, .right_2, .right_3, .right_4 {
flex: 1;
width: 50%;
margin-left: 50%;
background: lightblue;
}
.left {
position: absolute;
left: 0;
top: 70px;
width: 50%;
min-height: calc(100vh - 70px);
background: yellow;
}
#media only screen and (orientation: portrait) {
.wrapper * {
width: 100%;
margin: 0;
}
.left {
position: static;
flex: 1;
min-height: auto;
order: -1
}
.page-header {
order: -2;
}
}
<div class="wrapper">
<div class="page-header">Heading</div>
<h3 class="right_1">right_1</h3>
<div class="right_2">right_2</div>
<div class="left">form element</div>
<h3 class="right_3">right_3</h3>
<div class="right_4">right_4</div>
</div>
Probably the easiest way to change the order of div elements, you can use Jquery for this purpose. For example:
$("#element1").before($("#element2"));
Eventually:
CSS:
#blocks {
display: box;
box-orient: vertical;
}
#b1 {
box-ordinal-group: 2;
}
#b2 {
box-ordinal-group: 3;
}
HTML:
<div id="blocks">
<div id="b1">Block 1</div>
<div id="b2">Block 2</div>
<div id="b3">Block 3</div>
</div>
It should work.

CSS flexbox - is there a better way to do this?

The result I'm looking for is one big block on the left, and then four small blocks on the right, and everything aligns.
I managed to do this in this fiddle but my solution has a couple of problems:
- it's not very clean in terms of code
- it's not responsive
HTML:
<div class="wrapper">
<div class="box big">ONE</div>
<div class="med-wrapper">
<div class="row-1">
<div class="box medium">TWO</div>
<div class="box medium">THREE</div>
</div>
<div class="row-2">
<div class="box medium">FOUR</div>
<div class="box medium">FIVE</div>
</div>
</div>
</div>
CSS:
.wrapper {
display: flex;
flex-direction: row;
flex-flow: row wrap;
justify-content: space-around;
height: 200px;
}
/* #media screen and (max-width: 768px) {
flex-direction: column
} */
.box {
background: #09f;
color: white;
padding: 1em;
margin: 5px;
text-align: center;
}
.big {
flex: 5;
}
.medium {
flex: 5;
height: 100px;
}
.med-wrapper {
display: flex;
}
Also, you might notice that I have set the flex on both .big and .medium to 5, because I want the total width of the big box and the total width of two medium boxes to be equal, but it didn't work.
Is there a better way to do this?
It's tricky to have everything to align without getting into a lot of constraints, but using flexbox wrapping in the column direction on the right part could work.
Here's a quick version that uses a flex-flow: column wrap on the right part (.med-wrapper) and gets rid of the wrapper element on the two column wrappers inside it -
<div class="wrapper">
<div class="box big">
ONE
</div>
<div class="med-wrapper">
<div class="box medium">TWO</div>
<div class="box medium">THREE</div>
<div class="box medium">FOUR</div>
<div class="box medium">FIVE</div>
</div><!-- /.med-wrapper -->
</div><!-- /.wrapper -->
...and then the CSS:
body {
font-family: 'calibri', sans-serif;
margin: 0;
}
.wrapper {
display: flex;
justify-content: space-around;
height: 200px;
}
.box {
background: #09f;
color: white;
padding: 1em;
margin: 0 5px;
text-align: center;
box-sizing: border-box;
}
.big {
flex: 1;
height: 100%;
}
.med-wrapper {
flex: 1;
display: flex;
height: 100%;
flex-flow: column wrap;
justify-content: space-between;
overflow: auto;
}
.medium {
/* exact sizing for the medium boxes (i.e. get it from main sizing.) */
flex: 0 0 auto;
/* adjust for margins: */
width: calc(50% - 10px);
height: calc(50% - 5px);
}
/* some theoretical adjustments for smaller screens */
#media screen and (max-width: 768px) {
/* switch the wrapper to column dir, and remove fixed height. */
.wrapper {
flex-direction: column;
height: auto;
}
/* just a min height for demo purposes. */
.big {
min-height: 200px;
}
/* Now we need to re-set a height on this one, if we
want to keep the 2x2 square thing. */
.med-wrapper {
margin-top: 10px;
height: 200px;
}
}
Live demo at http://jsbin.com/kasez/5/edit
I've used calc()for the size calculations to counter margins, but hey, if you're already depending on flexbox, you probably need a fallback anyway. :-)
It should work with just the one explicit height on the .wrapper element, but the rest of the items should adjust accordingly - the downside is that overflow handling gets hard.
This is, incidentally, the type of "2D" situation (vs flexbox's 1D) that Grid Layout is meant to help with, but it'll be a while before that is a viable option.

Foundation - Reorganize blocks according to Foundation breakpoints

Here a coarse scaling of what I'm trying to do :
As you can see, I want to make several "organizations" of my three blocks :
On Large screens (and larger), I want them to be next to each other
On Medium screens, I want the first and the third block on the same row, and the second bloc on another row
On Small screens, I want them each to be one below the other
So, the problem appears on medium screens, the third block needs to be before the second block.
To solve it, I put the third block twice :
One between the first block and the second block (with the class rule "show-for-medium-only")
The other one after the second block (with the class rule "hide-for-medium-only")
Which gives me this html (you can see it in action here) :
<div class="row">
<div class="small-12 medium-4 large-3 columns">
<div class="panel">
1
</div>
</div>
<div class="show-for-medium-only medium-8 columns">
<div class="panel">
3
</div>
</div>
<div class="small-12 medium-12 large-5 columns">
<div class="panel">
2
</div>
</div>
<div class="hide-for-medium-only small-12 large-4 columns">
<div class="panel">
3
</div>
</div>
</div>
So my question is : Is there any ways to do it without duplicating the third block ? (Without using JavaScript, preferably with native Foundation rules)
You can use source-ordering or removing elements from the document flow and ordering them in layers with css and some html boilerplate:
http://jsfiddle.net/uw8U8/
html:
<div class="wrapper">
<div class="row layer-1">
<div class="small-12 medium-4 large-3 columns">
<div class="panel first">
1
</div>
</div>
<div class="small-12 medium-8 large-4 large-offset-5 third-column columns">
<div class="panel dummy"></div>
<div class="panel dummy"></div>
<div class="panel third">
3
</div>
</div>
</div>
<div class="row layer-2">
<div class=" medium-12 large-5 large-offset-3 columns">
<div class="panel second">
2
</div>
</div>
</div>
</div>
and app.scss
#import "settings";
#import "foundation";
.wrapper{
position: relative;
margin: auto;
max-width: $row-width;
}
.panel{
text-align: center;
height: 1.5em;
font-size: 1000%;
color: white;
}
.first{
background-color:#e64433;
}
.second{
background-color:#09afb9;
}
.third{
background-color:#ed9a24;
}
#media #{$large-up} {
.layer-1, .layer-2{
position: absolute;
}
}
.dummy{
display: none;
}
#media #{$small-only} {
.third-column{
position: absolute;
}
.dummy{
display: block;
visibility: hidden;
}
}
or css output for the default Foundation 5 setting:
.wrapper {
position: relative;
margin: auto;
max-width: 62.5rem;
}
/* line 11, ../scss/app.scss */
.panel {
text-align: center;
height: 1.5em;
font-size: 1000%;
color: white;
}
/* line 18, ../scss/app.scss */
.first {
background-color: #e64433;
}
/* line 21, ../scss/app.scss */
.second {
background-color: #09afb9;
}
/* line 24, ../scss/app.scss */
.third {
background-color: #ed9a24;
}
#media only screen and (min-width: 64.063em) {
/* line 30, ../scss/app.scss */
.layer-1, .layer-2 {
position: absolute;
}
}
/* line 35, ../scss/app.scss */
.dummy {
display: none;
}
#media only screen and (max-width: 40em) {
/* line 39, ../scss/app.scss */
.third-column {
position: absolute;
}
/* line 42, ../scss/app.scss */
.dummy {
display: block;
visibility: hidden;
}
}
Not really a Foundation oriented answer, but with display: grid; being widely supported, this solution should work with any CSS framework and will make the HTML much cleaner and the CSS much more flexible 😀 (by doing this, you also keep the styling out of the HTML document, which is a good practice and better for maintainability 😉)
The idea is to re-create a grid of 12 columns using :
display: grid;
grid-template-columns: repeat(12, 1fr);
And then span our panels on the corresponding number of columns using :
grid-column: span {{ number of column }};
Which gives us this :
html, body {
margin: 0;
padding: 0;
}
.grid {
display: grid;
grid-template-columns: repeat(12, 1fr); /* 1fr = 1 column */
grid-gap: 20px; /* gutter beetween each column and row */
margin: 20px;
}
.panel {
height: 180px;
line-height: 180px;
text-align: center;
font-size: 50px;
font-family: Impact, sans-serif;
color: #fff;
}
/* large screen */
.panel:nth-child(1) {
grid-column: span 3; /* 3 columns */
background-color: #e64433;
}
.panel:nth-child(2) {
grid-column: span 5; /* 5 columns */
background-color: #09afb9;
}
.panel:nth-child(3) {
grid-column: span 4; /* 4 columns */
background-color: #ed9a24;
}
/* medium screen */
#media (max-width: 1000px) {
.panel:nth-child(1) {
order: 1;
grid-column: span 4;
}
.panel:nth-child(2) {
order: 3;
grid-column: span 12;
}
.panel:nth-child(3) {
order: 2;
grid-column: span 8;
}
}
/* small screen */
#media (max-width: 600px) {
.panel:nth-child(1) {
order: 1;
grid-column: span 12;
}
.panel:nth-child(2) {
order: 2;
grid-column: span 12;
}
.panel:nth-child(3) {
order: 3;
grid-column: span 12;
}
}
<div class="grid">
<div class="panel">
1
</div>
<div class="panel">
2
</div>
<div class="panel">
3
</div>
</div>
You may also consider grid-template and grid-area which is a bit harder to understand at first sight, but may allow you to be more creative depending on your needs
Here is the result :
html, body {
margin: 0;
padding: 0;
}
.grid {
display: grid;
grid-template: "pannel1 pannel2 pannel3" auto / 3fr 5fr 4fr;
grid-gap: 20px;
margin: 20px;
}
.panel {
height: 180px;
line-height: 180px;
text-align: center;
font-size: 50px;
font-family: Impact, sans-serif;
color: #fff;
}
/* large screen */
.panel:nth-child(1) {
grid-area: pannel1;
background-color: #e64433;
}
.panel:nth-child(2) {
grid-area: pannel2;
background-color: #09afb9;
}
.panel:nth-child(3) {
grid-area: pannel3;
background-color: #ed9a24;
}
/* medium screen */
#media (max-width: 1000px) {
.grid {
grid-template:
"pannel1 pannel3" auto
"pannel2 pannel2" auto / 1fr 2fr;
}
}
/* small screen */
#media (max-width: 600px) {
.grid {
grid-template:
"pannel1" auto
"pannel2" auto
"pannel3" auto / 1fr;
}
}
<div class="grid">
<div class="panel">
1
</div>
<div class="panel">
2
</div>
<div class="panel">
3
</div>
</div>
Beware that the above solutions preserve the original document flow, which means, that if you want to "Tab" through the focusable elements of the page, it will always go to the second panel before the third, even though you'd expect to go to the third panel before the second on medium screens.
If it is a problem for you, you'll need either JS to automatically update tabindex properties on your pannels, or to re-order element in the HTML DOM itself, and if using JS is not a solution for you, then the code example in the original post is the only way to go I guess.
But remember that rearranging items in the DOM depending on the screen's size may not always be a good idea for accessibility :
Rearranging grid items visually does not affect the default traversal order of sequential navigation modes (such as cycling through links).
[CSS Grid Layout and Accessibility]