Line height rendering differently across browsers - html

I am creating a Grid layout like the following:
Each row contains 3 items and a divider line after these (and before next row).
Code is as follows:
HTML:
<div class="container">
<div class="item">ab</div> <!-- item -->
<div class="item">cdef</div> <!-- item -->
<div class="item">ghi</div> <!-- item -->
<div class="line"></div> <!-- divider line -->
<div class="item">jkl</div>
<div class="item">mno</div>
<div class="item">pq</div>
<div class="line"></div>
<div class="item">rs</div>
<div class="item">tuvw</div>
<div class="item">xyz</div>
<div class="line"></div>
</div>
CSS:
.container {
display: grid;
grid-template-columns: 1fr 1fr min-content;
}
.line {
grid-column: 1/4;
height: 1px;
width: 100%;
background: blue;
}
The problem is that the height of the divider line has a strange behavior. The following screenshots are taken from different browsers (Chrome & Firefox). Each time, one of the lines is rendered taller:
Inspecting DOM using Chrome Tools, height is always shown as 1px (as written in CSS). Therefore, it seems to be a rendering problem.
I suppose the problem is reproducible with this fiddle: https://jsfiddle.net/o96avqe8/
UPDATE:
The problem has nothing to do with Grid. It even occurs in the following minimal example:
HTML:
<div class="line"></div>
<div class="line"></div>
<div class="line"></div>
CSS:
.line {
width: 100%;
height: 1px;
background: blue;
margin-bottom: 20px;
}

I was not able to reproduce the problem you are describing.
Using your code, the layout renders the same on Firefox and Chrome.
But here's an idea that may fix the problem you are seeing: Try a different approach for generating the lines.
remove the lines from the HTML (for the sake of cleaner mark-up, they shouldn't be there anyway)
set a background color on the container
use the grid-row-gap property to generate the lines
.container {
display: grid;
grid-template-columns: 1fr 1fr min-content;
grid-row-gap: 1px;
background-color: blue;
border-bottom: 1px solid blue;
}
.item {
background-color: white;
}
<div class="container">
<div class="item">ab</div>
<div class="item">cdef</div>
<div class="item">ghi</div>
<div class="item">jkl</div>
<div class="item">mno</div>
<div class="item">pq</div>
<div class="item">rs</div>
<div class="item">tuvw</div>
<div class="item">xyz</div>
</div>

Related

Stop CSS grid contents from expanding to fill cell

I'm programming a web application with collapsible sidebar inside a CSS grid. The CSS grid divides the whole UI into sections, and the sidebar panel is a sub-component of one of those sections.
The issue I am running into is that I want the side panel to automatically shrink to the minimum size of it's contents, which it does fine until it's added to a CSS grid cell, at which point it expands to fill the entire cell.
Here is a quick example of the issue:
<style>
#myGrid{
display: grid;
grid-template-areas:
"g1 g2";
}
#panel{
grid-area: g2;
display: inline-block;
background: #FFAAAA;
height: 100%;
width: auto;
min-width: minmax(0, 1fr);
}
#panelContents{
display: flex;
flex-direction: row;
height: 100%;
}
#collapseArrow{
align-self: center;
right: 0;
top: 50%;
}
#block{
grid-area: g1;
width: 200px;
height: 100%;
background: #AAAAFF;
}
</style>
<body>
<div id="myGrid">
<div id="block">
Contents
</div>
<div id="panel">
<div id="panelContents">
<div id="collapseContents">
<div class="item">
Item1
</div>
<div class="item">
Item2
</div>
<div class="item">
Item3
</div>
<div class="item">
Item4
</div>
<div class="item">
Item5
</div>
</div>
<div id="collapseArrow"><</div>
</div>
</div>
</div>
</body>
Any idea how to solve this? I am trying to get the red panel to shrink to fit it's contents. I tried changing the min-width to 0, but that didn't seem to help.
EDIT: This is a more complex UI for an HTML5 game engine. The left grid cell is an asset browser, and the red panel is a simple properties panel for the right editor window (right grid cell), which I'm trying to display only on the left portion of the cell, so the rest of the right cell can be the editor window.
Use the other column to squeeze the panel down to its content width.
#myGrid {
display: grid;
grid-template-columns: 1fr auto; /* 1fr consumes all free space on the row */
grid-template-areas: "g1 g2";
}
#block {
grid-area: g1;
background: #AAAAFF;
}
#panel {
grid-area: g2;
background: #FFAAAA;
}
#panelContents {
display: flex;
}
#collapseArrow {
align-self: center;
}
<div id="myGrid">
<div id="block">
Contents
</div>
<div id="panel">
<div id="panelContents">
<div id="collapseContents">
<div class="item">Item1</div>
<div class="item">Item2</div>
<div class="item">Item3</div>
<div class="item">Item4</div>
<div class="item">Item5</div>
</div>
<div id="collapseArrow"><</div>
</div>
</div>
</div>

CSS grid create not equal grid

started using CSS grid instead of boostrap, and im having some issue to get it right.
i want to create a grid layout that have 4fr, and 8fr columns (just like boostrap 8 and 4 columns)
and when the divs inside the grid of 4r gets fill its the divs go to a second row just like flex-wrap:wrap.
BUT Its not work its only push it inline one after another, and ignoring the grid boundaries
.home {
display: grid;
grid-template-columns: 4fr 8fr;
grid-template-rows: 100%;
height: 100%;
}
<div class="home">
<div class="col-8">
</div>
<div class="col-4">
<mat-button-toggle-group class="side-menu-button">
<mat-button-toggle>test </mat-button-toggle>
<mat-button-toggle>test</mat-button-toggle>
<mat-button-toggle>test</mat-button-toggle>
<mat-button-toggle>test</mat-button-toggle>
<mat-button-toggle>test</mat-button-toggle>
<mat-button-toggle>test</mat-button-toggle>
<mat-button-toggle>test</mat-button-toggle>
<mat-button-toggle>test</mat-button-toggle>
</mat-button-toggle-group>
</div>
</div>
i even tried changing it to
grid-template-columns: repeat(1, auto-fill, 4fr 8fr);
If you're just wanting to use the grid to have items wrap inside of a div, what you're doing should basically work. Don't forget to tell .col-8 and .col-4 where they belong inside of the grid you've set up, and set the children you want to wrap to inline-block:
* {
box-sizing: border-box;
}
.home {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 100%;
height: 100%;
width: 100%;
grid-gap: 20px;
}
.col-8 {
grid-area: 1/1/1/9;
}
.col-4 {
grid-area: 1/9/1/13;
}
.bluebox,
.blackbox {
display: inline-block;
width: 50px;
height: 20px;
}
.bluebox {
background-color: blue;
}
.blackbox {
background-color: black;
}
<div class="home">
<div class="col-8">
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
<div class="bluebox"></div>
</div>
<div class="col-4">
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
<div class="blackbox"></div>
</div>
</div>
The reason I set up 12 columns instead of one that's 8fr and one that's 4fr is because I'm unclear about whether you're wanting a 12 column usable system like bootstrap (which is the way I implemented it), or literally only two columns. Either way should function for what you are describing in your question, but 12 separate columns is arguably more extensible later-on.
Here's a pen that contains the above code:
https://codepen.io/grantnoe/pen/MdOQOv
grid-area is what I used to set the location of .home's children. The format is as follows:
grid-area: <row-start> / <column-start> / <row-end> / <column-end>;
The only caveat is that you've nested the children you're wanting to wrap inside of secondary element <mat-button-toggle-group>. Consider adjusting the width of that element to 100% to fill the grid's child .col-4.

Combining the look of flex-start and space-between [duplicate]

This question already has answers here:
Targeting flex items on the last or specific row
(10 answers)
Wrapping flex items in the last row [duplicate]
(1 answer)
Closed 3 years ago.
I have a list of items I want to display with CSS. Originally, it was only two items side-by-side on one line but now I want to make it responsive for larger screens so I want to make it display 3 items on one line instead. My old code looks like this with justify-content:space-between. It looks good with an odd number of items to display.
.flex-container-old{
margin-top: 50px;
background: magenta;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.box-old{
width: 40%;
border: 1px solid black;
margin-bottom: 20px;
height: 300px;
background: orange;
}
.wrapper{
margin: 0 auto;
width: 80%;
}
body{
background:#D3D3D3;
}
<div class="wrapper">
<div class="flex-container-old">
<div class="box-old">
</div>
<div class="box-old">
</div>
<div class="box-old">
</div>
<div class="box-old">
</div>
<div class="box-old">
</div>
</div>
</div>
So naturally I extended it to three items in one row by modifying the width property only to end up with the below.
.flex-container-new{
background: lightblue;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.box {
width: 30%;
border: 1px solid black;
margin-bottom: 20px;
height: 300px;
background: orange;
}
.wrapper{
margin: 0 auto;
width: 80%;
}
<div class="wrapper">
<div class="flex-container-new">
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
</div>
</div>
My problem in the case of the above code with three items on one line is I want the last item in last row to be pushed to the left, aligned with the middle item in the row above it. Sadly bootstrap is not an option. This is for learning purposes. It there a way I can achieve the above with just CSS? Many thanks in advance.
This is easier to control using CSS Grid because we can dictate both the x and y axis. With Flexbox, you can only reliably control the x axis. If you haven't heard about the fr unit, it's defined by Mozilla as follows:
The fr, which is short for “fraction”, is a unit which represents a fraction of the available space in the grid container.
Another nice thing about using Grid is that we can drop the height and margin-bottom set in .box and also the flex-wrap rule. Everything about the layout of this grid, from the height of the cells to the grid-gap spacing between them, is all defined in the parent.
.grid-container-new {
background: lightblue;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, 300px);
grid-gap: 20px;
}
.box {
border: 1px solid black;
background: orange;
}
<div class="grid-container-new">
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
</div>
jsFiddle

Create a Table with CSS grid

I'm trying to create a table using CSS grid, with equal columns based on the content. I want to avoid using <table>. This is a follow-up to this question: Auto-adjusting columns with CSS grid
What I'm trying to achieve:
This table works: https://codepen.io/anon/pen/baExYw
But I want to wrap the each row in a div, which unsurprisingly breaks the table.
This table is broken: https://codepen.io/anon/pen/qpbMgG
app.html
<div class="wrapper">
<div class="box a">col 1</div>
<div class="box b">col 2</div>
<div class="box c">col 3</div>
<!-- Table Row -->
<div class="row">
<div class="box d">short data</div>
<div class="box e">a really long piece of data</div>
<div class="box f">short data</div>
</div>
<!-- Table Row -->
<div class="row">
<div class="box d">short data</div>
<div class="box e">a really long piece of data</div>
<div class="box f">short data</div>
</div>
</div>
app.css
.wrapper {
display: grid;
grid-template-columns: repeat(3, auto);
background-color: #fff;
color: #444;
max-width: 800px;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 20px;
font-size: 150%;
}
I'm still very new to CSS Grid, so I'm still having trouble understanding how half of this stuff works behind the scenes.
Any help is appreciated. Thanks in advance.
display: contents is what you need.
contents
These elements don't produce a specific box by themselves. They are
replaced by their pseudo-box and their child boxes.
Add this CSS (example):
.row {
display: contents;
}
More links:
Get Ready for `display: contents;`
Browser support table
In your first example, your data cells are children of the container. Hence, grid properties – which only work between parent and child – work as you expect.
In your second example, you have some data cells that are children of .row containers. These cells are no longer children of .wrapper, the grid container. Therefore, these cells are outside the scope of grid layout, do not recognize grid properties and are rendered as standard block-level elements.
So, basically, grid containers with different child elements render different layouts.
One solution to get your examples to match would be to make the grid items into grid containers having the same properties as the parent. Here's the general idea:
Revised Codepen
.wrapper {
display: grid;
grid-template-columns: repeat(3, minmax(50px, 1fr));
background-color: #fff;
color: #444;
max-width: 800px;
}
.row {
grid-column: 1 / -1;
display: grid;
grid-template-columns: repeat(3, minmax(50px, 1fr));
}
div:nth-child(4) { grid-row-start: 2; }
div:nth-child(5) { grid-row-start: 3; }
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 20px;
font-size: 150%;
}
<div class="wrapper">
<div class="box a">col 1</div>
<div class="box b">col 2</div>
<div class="box c">col 3</div>
<!-- Table Row -->
<div class="row">
<div class="box d">short data</div>
<div class="box e">a really long piece of data</div>
<div class="box f">short data</div>
</div>
<!-- Table Row -->
<div class="row">
<div class="box d">short data</div>
<div class="box e">a really long piece of data</div>
<div class="box f">short data</div>
</div>
</div>
It didn't break, it works exactly as intended.
Every child element is using one cell of the grid, if you wrap your header in another div you'll see they swap rows for columns, because each group will use one cell.
If you are going to display tabular data, then you should stick with tables as they are the semantically correct element for that purpose.
However if you are trying to build responsive designs or you really want to use grid I suggest you to read this incredible article about CSS grids.
Take a look in display: subgrid; maybe it is what you are looking for in this scenario.
Actually we should use auto-fit property of css-grid to create table-like layout with css gridNote: here because of auto-fit we do not need to specify the number of columns
#mixin table-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
align-items: center;
}
.tr{
#include table-row();
}
.thead{
#include table-row();
}
<HTML>
<div>
<div class="thead"></div>
<div class="tr"></div>
</div>
</html>

Make some items twice the height in a flexbox grid

I'm trying to create a simple flexbox grid with two columns, however with the option of declaring one of the children as "featured" making it twice the height of the normal children, so given the following markup:
<div class="container">
<div class="child featured">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
<div class="child">5</div>
<div class="child">6</div>
<div class="child">7</div>
</div>
You'd end up with something like this (margins/padding/border for illustrative purposes only):
However I can't seem to get it to work, the children all just stack under the featured child rather than fill the available space.
My basic CSS is:
.container {
display: flex;
flex-flow: column wrap;
}
.child {
flex: 1 0 50%;
height: 50vh;
max-width: 50%;
}
.child.featured {
height: 100vh;
}
Any idea what I'm doing wrong, or if there is a better approach to this (without resorting to JavaScript)?
Flexbox doesn't support such grid. But you can do it using floats:
.child {
float: left;
height: 50vh;
width: 50%;
outline: 1px solid red;
}
.child.featured {
height: 100vh;
}
<div class="container">
<div class="child featured">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
<div class="child">5</div>
<div class="child">6</div>
<div class="child">7</div>
</div>
Any idea what I'm doing wrong, or if there is a better approach to this (without resorting to JavaScript)?
The problem is that flexbox is not designed to create anything more than simple grids. Once you ask for something like a masonry layout (which is what you're after), you'll need hacks and workarounds for flexbox to complete the task.
However, this layout can be achieved easily in CSS Grid:
.container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 10px;
}
.child.featured {
grid-row-end: span 2;
}
/* non-essential decorative styles */
.container {
padding: 10px;
border: 2px solid gray;
background-color: lightgray;
height: 50vh;
}
.child {
background-color: deepskyblue;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.3em;
}
<div class="container">
<div class="child featured">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
<div class="child">5</div>
<div class="child">6</div>
<div class="child">7</div>
</div>
jsFiddle demo
For a complete explanation of the problem when using flexbox, and how the Grid functions work, see this post:
CSS-only masonry layout but with elements ordered horizontally