Within grid background image affected by content - css

This is kinda trickt to explain, but I got a nested grid, the grid inside the grid looks lite this:
.footer {
grid-area: footer;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
}
.bottomdiv {
grid-column-start: 1;
grid-column-end: 2;
text-align: center;
}
.leftdiv {
background-image: url("../images/logo-sbbq4.png");
opacity : 0.2;
background-repeat: no-repeat;
background-size: 20% 100%;
background-position: -60px 0px;
}
.contactlogo {
font-family: Neucha;
font-size: 4vw;
color: #000;
margin: 30% 4vw;
}
I got two problems, first one is probably easy, as you can see I want the bottomdiv to span across the 4 by 4 grid bottom.
The real problem I got is the leftdiv.
I have a backgroud image the I want to place a text above.
The image is placed and all is well but when I try to add the text the margin affects the image - I have placed it under due to CSS Cascadig nature but the didnt help.
The html looks like this:
<div class="footer" id="kontakt">
<div class="leftdiv contactlogo">
My BBQclass
</div>
<div class="rightdiv contacttext">
<ul>
<li>Telefon: 245213654</li>
<li>E-post: me#inter.net</li>
<li>Postgiro: 784512-22</li>
</ul>
</div>
<div class="bottomdiv ustext">Event, butiksevent, personalfester, fester och grillkurser. Kan även göra restaurang-gästspel med burgarna på begäran.</div>
</div>
So here is my noobish problem... wanting your excellent help.

Related

Can I group group dl/dd/dt displays two different ways on same page?

The following script displays exactly the same on each side of the screen. What I am trying to discover is how to group one set of dl/dt/dd definitions to be left side as normal with the dd below the dt as multiple lines but another group that will show the dt/dd on the same single lines.
I cannot figure out how to create two different dt/dd displays for the same page.
If you execute the script with the dl/dt/dd section commented out and then a second time with it in you will see the effects I'm trying to achieve, but both the multiple line and single line displays occurring on the same page as the same display. I'm thinking that there must be a way to define the CSS statements to act differently at different places on the same page. Obviously I would not do the displays in a real project, the side-by-side display is for question demonstration purposes only.
Is there a way to do this?
I tried creating a class with the modified dl/dt/dd statements and then be referenced as a class. That approach does not seem to work.
<!DOCTYPE html><html lang="en"><head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0, user-scalable=yes"/>
<title> DL/DT/DD Demos </title>
<!-- link rel="stylesheet" href="common.css" media="screen" -->
<!-- See: https://medium.com/#jakehyer/css-grid-auto-fit-minmax-e54f99989668 -->
<style>
main {
display: grid;
gap: 0.25rem;
}
/* 12.5rem (9 boxes), 16 (7), 18 (6), 20 (5), 25 (4), 33rem (3), 40rem (2) all work */
/* */
.gridCols9 { grid-template-columns: repeat(auto-fit,minmax(12.5rem, 1fr)); }
.gridCols7 { grid-template-columns: repeat(auto-fit,minmax(16rem, 1fr)); }
.gridCols6 { grid-template-columns: repeat(auto-fit,minmax(18rem, 1fr)); }
.gridCols5 { grid-template-columns: repeat(auto-fit,minmax(20rem, 1fr)); }
.gridCols4 { grid-template-columns: repeat(auto-fit,minmax(25rem, 1fr)); }
.gridCols3 { grid-template-columns: repeat(auto-fit,minmax(33rem, 1fr)); }
.gridCols2 { grid-template-columns: repeat(auto-fit,minmax(40rem, 1fr)); }
/* */
main > fieldset { border: 1px solid black; }
.fontInfo {
white-space: pre-wrap;
font-family: monospace;
}
h3 {
background-color: lightgreen; text-align: center;
font-size: 1.2rem; cursor: pointer;
margin: 0; padding: 0;
}
article { margin-top: 0; display: block; }
/* Following from: https://stackoverflow.com/questions/1713048/how-to-style-dt-and-dd-so-they-are-on-the-same-line */
/* Comment out following for entirely different display */
dl {
display: grid;
grid-template-columns: max-content auto;
}
dt { grid-column-start: 1; }
dd { grid-column-start: 2; }
/* */
</style>
</head><body>
<main class="gridCols4">
<fieldset> <legend> Normal </legend>
<article><h3>DL/DT/DD Display</h3></article>
<dl>
<dt>Mercury</dt>
<dd>Mercury (0.4 AU from the Sun) is the closest planet to the Sun and the smallest planet.</dd>
<dt>Venus</dt>
<dd>Venus (0.7 AU) is close in size to Earth, (0.815 Earth masses) and like Earth, has a thick silicate mantle around an iron core.</dd>
<dt>Earth</dt>
<dd>Earth (1 AU) is the largest and densest of the inner planets, the only one known to have current geological activity.</dd>
</dl>
</fieldset>
<fieldset> <legend> Modified </legend>
<article><h3>DL/DT/DD Display</h3></article>
<dl class="singleLines">
<dt>Mercury</dt>
<dd>Mercury (0.4 AU from the Sun) is the closest planet to the Sun and the smallest planet.</dd>
<dt>Venus</dt>
<dd>Venus (0.7 AU) is close in size to Earth, (0.815 Earth masses) and like Earth, has a thick silicate mantle around an iron core.</dd>
<dt>Earth</dt>
<dd>Earth (1 AU) is the largest and densest of the inner planets, the only one known to have current geological activity.</dd>
</dl>
</fieldset>
</main>
</body></html>
Maybe I'm missing something, but it seems like you just need to set the dt/dd's as child elements of dl with the '>' character. Here's an example showing the two different version views:
main {
display: grid;
gap: 0.25rem;
}
/* 12.5rem (9 boxes), 16 (7), 18 (6), 20 (5), 25 (4), 33rem (3), 40rem (2) all work */
/* */
.gridCols9 { grid-template-columns: repeat(auto-fit,minmax(12.5rem, 1fr)); }
.gridCols7 { grid-template-columns: repeat(auto-fit,minmax(16rem, 1fr)); }
.gridCols6 { grid-template-columns: repeat(auto-fit,minmax(18rem, 1fr)); }
.gridCols5 { grid-template-columns: repeat(auto-fit,minmax(20rem, 1fr)); }
.gridCols4 { grid-template-columns: repeat(auto-fit,minmax(25rem, 1fr)); }
.gridCols3 { grid-template-columns: repeat(auto-fit,minmax(33rem, 1fr)); }
.gridCols2 { grid-template-columns: repeat(auto-fit,minmax(40rem, 1fr)); }
/* */
main > fieldset { border: 1px solid black; }
.fontInfo {
white-space: pre-wrap;
font-family: monospace;
}
h3 {
background-color: lightgreen; text-align: center;
font-size: 1.2rem; cursor: pointer;
margin: 0; padding: 0;
}
article { margin-top: 0; display: block; }
/* Following from: https://stackoverflow.com/questions/1713048/how-to-style-dt-and-dd-so-they-are-on-the-same-line */
/* Comment out following for entirely different display */
dl.singleLines {
display: grid;
grid-template-columns: max-content auto;
}
dl.singleLines>dt { grid-column-start: 1; }
dl.singleLines>dd { grid-column-start: 2; }
<main class="gridCols4">
<fieldset>
<legend> Normal </legend>
<article>
<h3>DL/DT/DD Display</h3>
</article>
<dl>
<dt>Mercury</dt>
<dd>Mercury (0.4 AU from the Sun) is the closest planet to the Sun and the smallest planet.</dd>
<dt>Venus</dt>
<dd>Venus (0.7 AU) is close in size to Earth, (0.815 Earth masses) and like Earth, has a thick silicate mantle around an iron core.</dd>
<dt>Earth</dt>
<dd>Earth (1 AU) is the largest and densest of the inner planets, the only one known to have current geological activity.</dd>
</dl>
</fieldset>
<fieldset>
<legend> Modified </legend>
<article>
<h3>DL/DT/DD Display</h3>
</article>
<dl class="singleLines">
<dt>Mercury</dt>
<dd>Mercury (0.4 AU from the Sun) is the closest planet to the Sun and the smallest planet.</dd>
<dt>Venus</dt>
<dd>Venus (0.7 AU) is close in size to Earth, (0.815 Earth masses) and like Earth, has a thick silicate mantle around an iron core.</dd>
<dt>Earth</dt>
<dd>Earth (1 AU) is the largest and densest of the inner planets, the only one known to have current geological activity.</dd>
</dl>
</fieldset>
</main>

Trying to add Text to CSS Grid

I am trying to create a grid template in the style of a resume.
Basically, I have a grid that has 2 columns 1 fr and 3fr.
The 1fr has the title of the section and the 3fr has all the content.
In of the 3fr sections, I am putting work experience, and I have it laid out so that the there are 2 columns with a property of display: flex
Each is in a section with a div.
Now it looks good when I add the first job but then I add a second job and it layers it on top of first and so on. I want them to be under each other basically in their own row within that section.
How do I make it so that they do not stack on each other but are rather neatly laid one right after another?
Do I need to make ANOTHER grid within that grid row?
Any help would be great please check my Codepen below
(this is just a snippet please see below for full codepen)
Resume Codepen
.container {
display: grid;
max-width: 82em;
max-height: auto;
margin: auto;
grid-template-areas: "head head"
"nav nav"
"about about-info"
"work work-info"
"education education-info"
"skills skills-info"
"footer footer";
grid-template-rows: 300px 50px 12.50em 31em 500px 500px 50px;
grid-template-columns: 1fr 3fr;
grid-gap: .075em;
background-color: white;
}
.work-info {
border: 1px solid black;
grid-area: work-info;
display: flex;
}
You just have to add 'work-info' elements into one separate 'section/div' and need to change grid-template-rows: 300px 50px 12.50em auto 500px 500px 50px;
See the following link for working example:
https://codepen.io/anon/pen/GGZPPy?editors=1100
I can see that you are trying to place all of the content into a single CSS grid, but this isn't necessary.
Instead, why not display each <section> using display: grid?
Then you can customise the grid for each section as needed in the CSS stylesheet.
Working Example:
body {
font-family: arial, helvetica, sans-serif;
}
h2 {
font-size: 18px;
}
h3, p {
font-size: 16px;
}
header, main section {
padding: 0 6px;
box-shadow: 2px 2px 3px rgb(127, 127, 127);
}
main section div {
padding: 4px 6px;
border-right: 1px solid rgb(227, 227, 227);
}
main section div:last-of-type {
border-right: none;
}
main section {
display: grid;
max-width: 82em;
grid-template-columns: 25% 75%;
margin-bottom: 24px;
}
main section.work {
display: grid;
max-width: 82em;
grid-template-columns: 25% 25% 50%;
grid-template-rows: repeat(2, auto);
}
main section.work div:nth-of-type(1) {
grid-area: 1 / 1 / span 2 / 2;
}
<header><h1>Resume</h1></header>
<main>
<section class="about">
<div>
<h2>Nylma Jorns</h2>
<p>Reading and Writing Specialist</p>
</div>
<div>
<p>Caring, and enthusiastic educator with a strong commitment to student development and the learning experience. Excellent background and proven success in helping students reach their full potential.</p>
<p>Objective: To utilize the education and developing skills in teaching I have acquired over the years of teaching within the elementary grade level. To ensure that all students receive quality, rigorous, and data-driven instruction to ensure that all become self-reliant problem solvers. To help all students achieve goals and become life-long learners.</p>
</div>
</section>
<section class="work">
<div>
<h2>Work Experience</h2>
</div>
<div class="work-title">
<h3>Teacher</h3>
<p class="small">Fort Worth Independent School District</p>
<p class="small"><strong>Period:</strong> 2011 - Present<br>
<strong>Job type:</strong> Full-Time<br>
<strong>References:</strong> Seretha Lofton, Mrs. Staten</p>
</div>
<div class="work-description">
<h3>1st, 3rd, and 4th Grade Teacher (ESL, Self-Contained, Departmentalized, Two-Way DL, Team Teacher)</h3>
<ul>
<li>Maintain complete responsibility for the organization, teaching, and implementation of Curriculum</li>
<li>Successfully analyze student data to plan accordingly and meet various needs</li>
<li>Successfully implement interventions, centers, whole group, small groups, and technology</li>
<li>Implemented a positive discipline plan which promotes student responsibility and accountability</li>
<li>Lead PLCS to ensure that student achievement is the end goal</li>
<li>Knowledge of TEKS and student expectations</li>
</ul>
</div>
<div>
<h3>Reading and Math Interventionist, K-8th Grade</h3>
<p class="small">Catapult Learning</p>
<p class="small">
<strong>Period:</strong> 2011 - 2011<br>
<strong>Job type:</strong> Part-Time
</div>
<div>
<h3>Analyzed student data using various assessment tools, plan accordingly, and provide interventions in small groups using best practices</h3>
<ul>
<li>Maintain complete responsibility for the organization, teaching, and implementation of Curriculum</li>
<li>Successfully analyze student data to plan accordingly and meet various needs</li>
<li>Successfully implement interventions, centers, whole group, small groups, and technology</li>
<li>Implemented a positive discipline plan which promotes student responsibility and accountability</li>
<li>Lead PLCS to ensure that student achievement is the end goal</li>
<li>Knowledge of TEKS and student expectations</li>
</ul>
</div>
</section>
<section class="education">
<div>
<h2>Education</h2>
</div>
<div>Education Stuff</div>
</section>
<section class="skills">
<div>
<h2>Skills</h2>
</div>
<div>Skills Stuff</div>
</section>
</main>

CSS Grid auto placement in IE/EDGE

While using the old CSS grid spec that is supported by IE 11 and EDGE. Is it possible for the grid items to be auto placed like the current spec?
i.e. to not have to define the column on a grid item:
.item:nth-child(1) {
-ms-grid-column: 1;
}
.item:nth-child(2) {
-ms-grid-column: 2;
}
.item:nth-child(n) {
-ms-grid-column: n;
}
https://codepen.io/JoeHastings/pen/mMPoqB
The answer is NO (unfortunately).
Old specs section about auto-placement has such preamble
This section describes early thinking around automatic placement of Grid Items. Multiple algorithms are possible for such a feature. One is proposed here.
Run this code in IE/Edge and you'll see a lot of rows with 1 in console because IE/Edge stacks all grid items in first cell and you can't force IE/Edge to place grid items automatically. Setting -ms-grid-column and -ms-grid-row to auto won't change anything, because this value is not supported (as you can see in MSDN links). Demo:
var gridItems = document.querySelectorAll(".grid__item");
for (var i = 0; i < gridItems.length; i++) {
var gridItem = gridItems[i];
console.log(window.getComputedStyle(gridItem)["-ms-grid-row"]);
console.log(window.getComputedStyle(gridItem)["-ms-grid-column"]);
}
.grid {
display: -ms-grid;
-ms-grid-columns: 100px 100px 100px;
-ms-grid-rows: 100px 100px 100px;
}
.grid__item {
-ms-grid-row: auto;
-ms-grid-column: auto;
background-color: tomato;
color: white;
font-size: 20px;
display: flex;
align-items: center;
justify-content: center;
}
<div class="grid">
<div class="grid__item">One</div>
<div class="grid__item">Two</div>
<div class="grid__item">Three</div>
<div class="grid__item">Four</div>
<div class="grid__item">Five</div>
<div class="grid__item">Six</div>
<div class="grid__item">Seven</div>
<div class="grid__item">Eight</div>
<div class="grid__item">Nine</div>
</div>

Horizontal center for flex items [duplicate]

I want the flex items to be centered but when we have a second line, to have 5 (from image below) under 1 and not centered in the parent.
Here's an example of what I have:
ul {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
margin: 0;
padding: 0;
}
li {
list-style-type: none;
border: 1px solid gray;
margin: 15px;
padding: 5px;
width: 200px;
}
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul>
http://jsfiddle.net/8jqbjese/2/
Flexbox Challenge & Limitation
The challenge is to center a group of flex items and left-align them on wrap. But unless there is a fixed number of boxes per row, and each box is fixed-width, this is currently not possible with flexbox.
Using the code posted in the question, we could create a new flex container that wraps the current flex container (ul), which would allow us to center the ul with justify-content: center.
Then the flex items of the ul could be left-aligned with justify-content: flex-start.
#container {
display: flex;
justify-content: center;
}
ul {
display: flex;
justify-content: flex-start;
}
This creates a centered group of left-aligned flex items.
The problem with this method is that at certain screen sizes there will be a gap on the right of the ul, making it no longer appear centered.
This happens because in flex layout (and, actually, CSS in general) the container:
doesn't know when an element wraps;
doesn't know that a previously occupied space is now empty, and
doesn't recalculate its width to shrink-wrap the narrower layout.
The maximum length of the whitespace on the right is the length of the flex item that the container was expecting to be there.
In the following demo, by re-sizing the window horizontally, you can see the whitespace come and go.
DEMO
A More Practical Approach
The desired layout can be achieved without flexbox using inline-block and media queries.
HTML
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul>
CSS
ul {
margin: 0 auto; /* center container */
width: 1200px;
padding-left: 0; /* remove list padding */
font-size: 0; /* remove inline-block white space;
see https://stackoverflow.com/a/32801275/3597276 */
}
li {
display: inline-block;
font-size: 18px; /* restore font size removed in container */
list-style-type: none;
width: 150px;
height: 50px;
line-height: 50px;
margin: 15px 25px;
box-sizing: border-box;
text-align: center;
}
#media screen and (max-width: 430px) { ul { width: 200px; } }
#media screen and (min-width: 431px) and (max-width: 630px) { ul { width: 400px; } }
#media screen and (min-width: 631px) and (max-width: 830px) { ul { width:600px; } }
#media screen and (min-width: 831px) and (max-width: 1030px) { ul { width: 800px; } }
#media screen and (min-width: 1031px) and (max-width: 1230px) { ul { width: 1000px; } }
The above code renders a horizontally-centered container with left-aligned child elements like this:
DEMO
Other Options
Properly sizing and aligning the flex item(s) on the last row
Desandro Masonry
Masonry is a JavaScript grid layout library. It
works by placing elements in optimal position based on available
vertical space, sort of like a mason fitting stones in a wall. You’ve
probably seen it in use all over the Internet.
source: http://masonry.desandro.com/
CSS Grid Layout Module Level 1
This CSS module defines a two-dimensional grid-based layout system, optimized for user interface design. In the grid layout model, the children of a grid container can be positioned into arbitrary slots in a predefined flexible or fixed-size layout grid.
source: https://drafts.csswg.org/css-grid/
You can achieve it with CSS Grid, just use repeat(autofit, minmax(width-of-the-element, max-content))
ul {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(210px, max-content));
grid-gap: 16px;
justify-content: center;
padding: initial;
}
li {
list-style-type: none;
border: 1px solid gray;
padding: 5px;
width: 210px;
}
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
</ul>
http://jsfiddle.net/rwa20jkh/
Somehow, #Joe82 answer did not work for me. However, I found it to be the right approach. After reading this article about auto-fit and auto-fill I found out that auto-fit creates new columns when possible; however, it collapses them, so that the grid-items fill out the whole available space, if their max-width allows them this.
For those interested: auto-fill also creates new columns when possible, but does not let them collapse, so it creates empty visible columns, which will take up space.
You can see this in the following image:
Because of this, I used repeat(auto-fit, minmax(10rem, 1fr) for `grid-template-columns.
Then I set justify-items to center, this aligns the items inside their grid areas on the inline axis.
I also wanted some "margins" between the columns and rows, so I added a row-gap and a column-gap of 1rem with the shorthand.
As a result I added the following CSS to my div with the grid items inside it:
.card-section {
width: 100%;
display: grid;
justify-items: center;
gap: 1rem;
grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
}
I know this is not exactly what OP wanted to achieve, but maybe it helps someone, who has the same problem as me and stumbles upon this question.
You can place invisible elements with the same class as the others (removed on example for exibition purposes) and height set to 0. With that, you will be able to justify the items to the very start of the grid.
Example
<div class="table-container">
<div class="table-content">
<p class="table-title">Table 1</p>
<p class="mesa-price">$ 20</p>
</div>
<!-- Make stuff justified start -->
<div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
<div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
<div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
<div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
</div>
Result
As #michael suggested, this is a limitation with current flexbox. But if you want to still use flex and justify-content: center;, then we can workaround this by adding a dummy li element and assign margin-left.
const handleResize = () => {
const item_box = document.getElementById('parentId')
const list_length = item_box.clientWidth
const product_card_length = 200 // length of your child element
const item_in_a_row = Math.round(list_length/product_card_length)
const to_be_added = item_in_a_row - parseInt(listObject.length % item_in_a_row) // listObject is the total number items
const left_to_set = (to_be_added - 1 ) * product_card_length // -1 : dummy item has width set, so exclude it when calculating the left margin
const dummy_product = document.querySelectorAll('.product-card.dummy')[0]
dummy_product.style.marginLeft = `${left_to_set}px`
}
handleResize() // Call it first time component mount
window.addEventListener("resize", handleResize);
Check this fiddle (resize and see ) or video for reference
One way to get the desired style with margins is to do the following:
#container {
display: flex;
justify-content: center;
}
#innercontainer {
display: flex;
flex: 0.9; -> add desired % of margin
justify-content: flex-start;
}
I ran into this problem while coding with React Native. There's an elegant solution that you can have using FlexBox. In my particular situation, I was trying to center three flex boxes (Flex: 2) inside another using alignItems. The solution I came up with was using two empty s, each with Flex: 1.
<View style={{alignItems: 'center', flexWrap: 'wrap', flexDirection: 'row'}}>
<View style={{flex: 1}} />
// Content here
<View style={{flex: 1}} />
</View>
Easy enough to convert to web / CSS.
The easiest way I've found to fix this is just simply add some place holders with visibility: hidden. That way it maintains the correct spacing as it wraps.
TL;DR
You can stuff some filler elements to the end of your container, and set visibility: hidden to make it invisible, and remember to set height: 0px to prevent the height be taken.
Demo
In the example below, you can click the button to watch the changes.
const container = document.getElementsByClassName('container')[0];
const item = document.createElement('div');
item.classList.add("item");
const filler = document.createElement('div')
filler.classList.add("filler");
item.appendChild(filler);
Array.from(Array(5).keys()).forEach(() => {
container.appendChild(item.cloneNode(true));
});
function onShowClick() {
const filler = document.getElementsByClassName('filler')
for (let i = 0; i < filler.length; i++) {
filler[i].style.border = "1px dashed #686868"
filler[i].style.visibility = "visible"
filler[i].style.height = "100px"
}
};
function onHideClick() {
const filler = document.getElementsByClassName('filler')
for (let i = 0; i < filler.length; i++) {
filler[i].style.border = "none"
filler[i].style.visibility = "hidden"
filler[i].style.height = "0px"
}
};
* {
box-sizing: border-box;
}
#root {
height: 400px;
width: 500px;
border: 1px solid #ff955a;
}
.container {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.item {
padding: 5px;
}
.content-box {
height: 100px;
width: 100px;
padding: 10px;
background-color: lightblue;
border-radius: 10px;
}
.filler {
visibility: hidden;
height: 0px;
width: 100px;
}
<div id="root">
<button onclick="onShowClick()">Show</button>
<button onclick="onHideClick()">Hide</button>
<div class="container">
<div class="item">
<div class="content-box">1</div>
</div>
<div class="item">
<div class="content-box">2</div>
</div>
<div class="item">
<div class="content-box">3</div>
</div>
<div class="item">
<div class="content-box">4</div>
</div>
<div class="item">
<div class="content-box">5</div>
</div>
<div class="item">
<div class="content-box">6</div>
</div>
<div class="item">
<div class="content-box">7</div>
</div>
<div class="item">
<div class="content-box">8</div>
</div>
<div class="item">
<div class="content-box">9</div>
</div>
</div>
</div>

Flexbox quirks, centering of grid [duplicate]

I want the flex items to be centered but when we have a second line, to have 5 (from image below) under 1 and not centered in the parent.
Here's an example of what I have:
ul {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
margin: 0;
padding: 0;
}
li {
list-style-type: none;
border: 1px solid gray;
margin: 15px;
padding: 5px;
width: 200px;
}
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul>
http://jsfiddle.net/8jqbjese/2/
Flexbox Challenge & Limitation
The challenge is to center a group of flex items and left-align them on wrap. But unless there is a fixed number of boxes per row, and each box is fixed-width, this is currently not possible with flexbox.
Using the code posted in the question, we could create a new flex container that wraps the current flex container (ul), which would allow us to center the ul with justify-content: center.
Then the flex items of the ul could be left-aligned with justify-content: flex-start.
#container {
display: flex;
justify-content: center;
}
ul {
display: flex;
justify-content: flex-start;
}
This creates a centered group of left-aligned flex items.
The problem with this method is that at certain screen sizes there will be a gap on the right of the ul, making it no longer appear centered.
This happens because in flex layout (and, actually, CSS in general) the container:
doesn't know when an element wraps;
doesn't know that a previously occupied space is now empty, and
doesn't recalculate its width to shrink-wrap the narrower layout.
The maximum length of the whitespace on the right is the length of the flex item that the container was expecting to be there.
In the following demo, by re-sizing the window horizontally, you can see the whitespace come and go.
DEMO
A More Practical Approach
The desired layout can be achieved without flexbox using inline-block and media queries.
HTML
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul>
CSS
ul {
margin: 0 auto; /* center container */
width: 1200px;
padding-left: 0; /* remove list padding */
font-size: 0; /* remove inline-block white space;
see https://stackoverflow.com/a/32801275/3597276 */
}
li {
display: inline-block;
font-size: 18px; /* restore font size removed in container */
list-style-type: none;
width: 150px;
height: 50px;
line-height: 50px;
margin: 15px 25px;
box-sizing: border-box;
text-align: center;
}
#media screen and (max-width: 430px) { ul { width: 200px; } }
#media screen and (min-width: 431px) and (max-width: 630px) { ul { width: 400px; } }
#media screen and (min-width: 631px) and (max-width: 830px) { ul { width:600px; } }
#media screen and (min-width: 831px) and (max-width: 1030px) { ul { width: 800px; } }
#media screen and (min-width: 1031px) and (max-width: 1230px) { ul { width: 1000px; } }
The above code renders a horizontally-centered container with left-aligned child elements like this:
DEMO
Other Options
Properly sizing and aligning the flex item(s) on the last row
Desandro Masonry
Masonry is a JavaScript grid layout library. It
works by placing elements in optimal position based on available
vertical space, sort of like a mason fitting stones in a wall. You’ve
probably seen it in use all over the Internet.
source: http://masonry.desandro.com/
CSS Grid Layout Module Level 1
This CSS module defines a two-dimensional grid-based layout system, optimized for user interface design. In the grid layout model, the children of a grid container can be positioned into arbitrary slots in a predefined flexible or fixed-size layout grid.
source: https://drafts.csswg.org/css-grid/
You can achieve it with CSS Grid, just use repeat(autofit, minmax(width-of-the-element, max-content))
ul {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(210px, max-content));
grid-gap: 16px;
justify-content: center;
padding: initial;
}
li {
list-style-type: none;
border: 1px solid gray;
padding: 5px;
width: 210px;
}
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
</ul>
http://jsfiddle.net/rwa20jkh/
Somehow, #Joe82 answer did not work for me. However, I found it to be the right approach. After reading this article about auto-fit and auto-fill I found out that auto-fit creates new columns when possible; however, it collapses them, so that the grid-items fill out the whole available space, if their max-width allows them this.
For those interested: auto-fill also creates new columns when possible, but does not let them collapse, so it creates empty visible columns, which will take up space.
You can see this in the following image:
Because of this, I used repeat(auto-fit, minmax(10rem, 1fr) for `grid-template-columns.
Then I set justify-items to center, this aligns the items inside their grid areas on the inline axis.
I also wanted some "margins" between the columns and rows, so I added a row-gap and a column-gap of 1rem with the shorthand.
As a result I added the following CSS to my div with the grid items inside it:
.card-section {
width: 100%;
display: grid;
justify-items: center;
gap: 1rem;
grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
}
I know this is not exactly what OP wanted to achieve, but maybe it helps someone, who has the same problem as me and stumbles upon this question.
You can place invisible elements with the same class as the others (removed on example for exibition purposes) and height set to 0. With that, you will be able to justify the items to the very start of the grid.
Example
<div class="table-container">
<div class="table-content">
<p class="table-title">Table 1</p>
<p class="mesa-price">$ 20</p>
</div>
<!-- Make stuff justified start -->
<div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
<div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
<div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
<div class="table-content" style="opacity: 0; cursor: default; height: 0; margin-bottom: 0;"></div>
</div>
Result
As #michael suggested, this is a limitation with current flexbox. But if you want to still use flex and justify-content: center;, then we can workaround this by adding a dummy li element and assign margin-left.
const handleResize = () => {
const item_box = document.getElementById('parentId')
const list_length = item_box.clientWidth
const product_card_length = 200 // length of your child element
const item_in_a_row = Math.round(list_length/product_card_length)
const to_be_added = item_in_a_row - parseInt(listObject.length % item_in_a_row) // listObject is the total number items
const left_to_set = (to_be_added - 1 ) * product_card_length // -1 : dummy item has width set, so exclude it when calculating the left margin
const dummy_product = document.querySelectorAll('.product-card.dummy')[0]
dummy_product.style.marginLeft = `${left_to_set}px`
}
handleResize() // Call it first time component mount
window.addEventListener("resize", handleResize);
Check this fiddle (resize and see ) or video for reference
One way to get the desired style with margins is to do the following:
#container {
display: flex;
justify-content: center;
}
#innercontainer {
display: flex;
flex: 0.9; -> add desired % of margin
justify-content: flex-start;
}
I ran into this problem while coding with React Native. There's an elegant solution that you can have using FlexBox. In my particular situation, I was trying to center three flex boxes (Flex: 2) inside another using alignItems. The solution I came up with was using two empty s, each with Flex: 1.
<View style={{alignItems: 'center', flexWrap: 'wrap', flexDirection: 'row'}}>
<View style={{flex: 1}} />
// Content here
<View style={{flex: 1}} />
</View>
Easy enough to convert to web / CSS.
The easiest way I've found to fix this is just simply add some place holders with visibility: hidden. That way it maintains the correct spacing as it wraps.
TL;DR
You can stuff some filler elements to the end of your container, and set visibility: hidden to make it invisible, and remember to set height: 0px to prevent the height be taken.
Demo
In the example below, you can click the button to watch the changes.
const container = document.getElementsByClassName('container')[0];
const item = document.createElement('div');
item.classList.add("item");
const filler = document.createElement('div')
filler.classList.add("filler");
item.appendChild(filler);
Array.from(Array(5).keys()).forEach(() => {
container.appendChild(item.cloneNode(true));
});
function onShowClick() {
const filler = document.getElementsByClassName('filler')
for (let i = 0; i < filler.length; i++) {
filler[i].style.border = "1px dashed #686868"
filler[i].style.visibility = "visible"
filler[i].style.height = "100px"
}
};
function onHideClick() {
const filler = document.getElementsByClassName('filler')
for (let i = 0; i < filler.length; i++) {
filler[i].style.border = "none"
filler[i].style.visibility = "hidden"
filler[i].style.height = "0px"
}
};
* {
box-sizing: border-box;
}
#root {
height: 400px;
width: 500px;
border: 1px solid #ff955a;
}
.container {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.item {
padding: 5px;
}
.content-box {
height: 100px;
width: 100px;
padding: 10px;
background-color: lightblue;
border-radius: 10px;
}
.filler {
visibility: hidden;
height: 0px;
width: 100px;
}
<div id="root">
<button onclick="onShowClick()">Show</button>
<button onclick="onHideClick()">Hide</button>
<div class="container">
<div class="item">
<div class="content-box">1</div>
</div>
<div class="item">
<div class="content-box">2</div>
</div>
<div class="item">
<div class="content-box">3</div>
</div>
<div class="item">
<div class="content-box">4</div>
</div>
<div class="item">
<div class="content-box">5</div>
</div>
<div class="item">
<div class="content-box">6</div>
</div>
<div class="item">
<div class="content-box">7</div>
</div>
<div class="item">
<div class="content-box">8</div>
</div>
<div class="item">
<div class="content-box">9</div>
</div>
</div>
</div>

Resources