Is it bad practice to nest CSS Grids? - html

I'm experimenting with component driven front end frameworks, such as Angular, and finally learning CSS Grid.
My question is: is it bad practice to nest CSS Grids?
What I've done here is in my main/root component, I've used css grid to make two things: the navbar and the main content area, since navbar will be present in the entire app and also the main content.
As you can see below, the grid on the root level then another grid in the <nav-bar> component. And in the main content area, there will be many more, probably a grid in each/any Angular component I use.
********************** ******************************
* Navbar * => * img | nav | logout *
********************** ******************************
**********************
* *
* Content *
* *
**********************
Example code below:
app.component.html
<div class="container">
<div class="item-navbar"></div>
<div class="item-nav">
<nav-bar></nav-bar>
</div>
<div class="item-content">
<router-outlet></router-outlet>
</div>
</div>
<!-- With this CSS: -->
<style>
.container {
display: grid;
grid: ". nav ."
". content ."
/ 3vh auto 3vh;
row-gap: 1vh;
}
.item-navbar {
grid-area: 1 / 1 / 2 / 4;
position: relative;
z-index: -1;
background: #579C87;
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
}
.item-nav {
grid-area: nav;
}
.item-content {
grid-area: content;
background: #D1C7B8;
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
}
</style>
then
nav-bar.component.html
<nav class="navbar" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<a class="navbar-item" routerLink="/">
<div class="img">
<img src="logo.jpg">
</div>
</a>
</div>
<div class="navbar-menu">
<a routerLink="/dashboard" class="navbar-item">Dashboard</a>
</div>
<div class="navbar-logout">
<a routerLink="/logout" class="navbar-item">Logout</a>
</div>
</nav>
<!-- with this CSS: -->
<style>
.navbar {
display: grid;
grid-template-columns: 64px auto auto;
grid-template-rows: auto;
grid-template-areas: "image navs logout";
gap: 1vh;
}
.navbar-brand {
grid-area: image;
place-self: center / start;
}
.navbar-menu {
grid-area: navs;
place-self: center start;
}
.navbar-logout {
grid-area: logout;
place-self: center end;
}
</style>

There is nothing wrong or invalid with nesting grid containers.
The grid specification doesn't prohibit, or even admonish, against the practice. It says this:
Grid containers can be nested or mixed with flex containers as necessary to create more complex layouts.
In fact, nesting grid containers is what you must do to apply grid properties to the descendants of a top-level container, since grid layout works only between parent and child elements.
More details here:
Grid properties not working on elements inside grid container
Positioning content of grid items in primary container (subgrid feature)

It is not bad practice, it is recommended for proper display.
I have one caveat to mention, separate each nested level into its own file for debugging purposes. When nesting multiple levels deep, a single missing or misplaced </div> can significantly alter the output and will be very hard to debug. My suggestion is any further nesting also should be split out into separate components, so each level can be tested independently.

To answer your question, it is an acceptable practice to nest grid or flex components: csswg
Here is an example that demonstrates a nested grid: gridbyexample

Nesting grid containers is an acceptable practice.

Related

How switch Bootstrap 5 columns order while its nested (without hidden duplicates)?

The following code is supposed to display blocks for mobile and desktop view in different ways.
<div class="col-12 col-sm-6 order-sm-1">TITLE</div>
<div class="col-12 col-sm-6 order-sm-0">IMAGE</div>
<div class="col-12 col-sm-6 order-sm-2 offset-sm-6">DESCRIPTION</div>
This code represents blocks on desktop in this way. On desktop view blocks IMAGE and TITLE will have same height.
--------------- ---------------
-----IMAGE----- -----TITLE-----
--------------- ---------------
--------------- ---------------
--------------- --DESCRIPTION--
--------------- ---------------
But I want to display these blocks (on desktop) in this way. Description block should be under title block. Both of them should represent right half of screen.
--------------- ---------------
--------------- -----TITLE-----
-----IMAGE----- ---------------
--------------- --DESCRIPTION--
--------------- ---------------
How I can do that?
Important to add that we can't use double blocks using hidden classes to switch its visibility in different views (because of SEO).
You can only use order on sibling elements.
The order property specifies the order of a flexible item relative to
the rest of the flexible items inside the same container.
A no JS solution with all the columns in the same container using Flex is definitely possible utilizing flex-basis, but there is a drawback...
... you need a height:
Use Dev Tools to watch them collapse below the small breakpoint.
.row {
height: 150px;
}
#media (min-width: 576px) {
.col:nth-child(2) {
flex: 0 100% !important;
background: lightblue;
}
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
<div class="container">
<div class="row row-cols-1 row-cols-sm-2 flex-column justify-content-sm-center">
<div class="col order-sm-2">TITLE</div>
<div class="col order-sm-1 d-flex justify-content-sm-center align-items-sm-center">IMAGE</div>
<div class="col order-sm-3">DESCRIPTION</div>
</div>
</div>
But who wants to work with heights in 2023? And don't forget:
Authors must not use order or the *-reverse values of
flex-flow/flex-direction as a substitute for correct source ordering,
as that can ruin the accessibility of the document.
Perhaps try and use grid to create your layout. No need for any ordering then:
/* Create two columns of equal size. */
.grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: auto;
}
/* Let each grid-item by default span 2 columns... */
.grid-item {
grid-column: span 2;
}
#media (min-width: 576px) {
/* ...but only span 1 column above Bootstrap's SM breakpoint. */
.grid-item {
grid-column: span 1;
}
/* Let IMAGE start on row 1 and span 2 rows. */
.grid-item:nth-child(2) {
grid-row: 1 / span 2;
}
}
/* COLORS */
.grid-item:nth-child(1) {
background: lightgreen;
}
.grid-item:nth-child(2) {
background: lightyellow;
}
.grid-item:nth-child(3) {
background: lightblue;
}
<div class="grid">
<div class="grid-item">TITLE</div>
<div class="grid-item">IMAGE</div>
<div class="grid-item">DESCRIPTION</div>
</div>
It's also possible to use Grid in Bootstrap.

Moving an element from a "stack" to a new line for small screens

This is what I want to achieve in Bootstrap:
The first one I can achieve by defining B and C under the common div.
The second one I can achieve by defining C separately on the new row.
I don't know how to get both of them.
I don't think it possible with just bootstrap, since it use flex-layout base class, and it can't do what you want (correct me if i'm wrong though, i haven't touch bootstrap much since v4 come out).
So what i'm suggest here is a custom grid-layout base class to the parent div of all 3 childs, which you can use with media query to custom layout the way you want. All other bootstrap classes can still use as normal otherwise. Basically i create a table like area with pre-defined sections, then i 'attach' the childs to their desire location.
*HTML
<div class="container">
<div class="row grid">
<div class="col_a col-6 col-md-12">Col A</div>
<div class="col_b col-6 col-md-12">Col B</div>
<div class="col_c col-12">Col C</div>
</div>
</div>
*CSS
.col_a {
background: red;
}
.col_b {
background: yellow;
}
.col_c {
background: green;
}
#media screen and (min-width: 768px) {
.grid {
display: grid;
grid-template-areas: "left right-top" "left right-bottom";
}
.col_a {
grid-area: left;
}
.col_b {
grid-area: right-top;
}
.col_c {
grid-area: right-bottom;
}
}
Demo - resize screen to see the effect.

Flexbox: Two even columns - big image (with aspect-ratio) and content

I need to create an information section that includes an image and content next to it.
It should look like this:
I have already written a little bit of code, but it does not seem to be the best solution: everything works fine, but code is not graceful.
Please, have a look:
/* Simple reset */
img {
display: block;
max-width: 100%;
}
body {
background-color: black;
}
.information {
display: flex;
gap: clamp(5rem, 10vw, 8rem);
}
.information > * {
width: 50%; /* Using the 'width' property. */
}
.information-content {
align-self: center;
color: white;
}
.information-image {
align-self: flex-start;
object-fit: cover;
aspect-ratio: 1 / 1.10;
border-radius: 5px;
}
<section>
<div class="container">
<div class="information">
<img
class="information-image"
alt="Products for companies & Startups"
src="https://s3-alpha-sig.figma.com/img/6630/3672/40959a0086f9fbb8418c0829b277dd93?Expires=1670198400&Signature=gpQ5NqRXp9omRHkjCl718I9WPLqfx4xPKp1CQSMKbEnRCU7izmQIXkcn6zI6Z17p8Q7Li-wBAXb3P2Jg9qEuJauFeKqErbl4jgW950K35-LeX394hN7fJ7UEPmkgGSqB-drY1QdU7NZVV4QKTrZ0QBuw47xVBPOOfJMQO8NPOpZkx43UbbkS1yGgnxN5tELyriz9e8pH6pXO8AnJx7zvGz4mm3InyHOySUcb3ibVPa9XKJ8fyxPnkBeVoYFvwpiVddEs7uVNqCkCRuN2dJIIQg78FB-6TYX13nQ~NxvhG2059ks2q52a9p0N-DSmSYE-Yt-jedbJ1fEt3cZVnIfzUw__&Key-Pair-Id=APKAINTVSUGEWH5XD5UA"
/>
<div class="information-content">
<h2>
My main goal is to keep my customers satisfied.
</h2>
<p>
Even with skills that are primarily mental, such as
computer programming or speaking a foreign language.
</p>
<p>
Even with skills that are primarily mental, such as
computer programming or speaking a foreign language.
</p>
</div>
</div>
</div>
</section>
My concern is the width property set on each child of my flex parent. As far as I know, using width inside flexbox is not the best idea? However, when I try to use the flex-basis property, everything breaks.
Note: I cannot use display: grid because the image can be after the content - with grid I will have to change the order and the code will become more complicated.

grid-template-areas doesn't take all columns for one div

I am building a page with grid.
And I am in a stuck with grid-template-areas.
I want that .cinema takes all space (2 column) and .why only first column.
But when I wrote .cinema twice, Chrome showed the grid-template-areas - "invalid property value"
Why does it happen?
.grid {
display: grid;
grid-gap: 0px;
grid-template-areas: "cinema" "why"
}
#media (min-width: 640px) {
.grid {
grid-template-columns: 1fr 1fr;
grid-template-areas: "cinema cinema" "why"
}
}
.cinema {
grid-area: cinema;
background: url(comigo/other/homepage-featured-new-1920x745.jpg) no repeat;
background-position: 100%;
background-size: cover;
text-align: center;
}
.why {
grid-area: why;
background: white;
text-align: center;
}
<div class="grid">
<div class="cinema">
<h3>Comigo OTT/STB solutions - redefine TV experience</h3>
<p>
<form>
<button>OUR SOLUTIONS</button>
</form>
</div>
<div class="why">
<h2> WHY COMIGO?</h2>
<h4>Comigo redefines the TV experience
<p>
<form>
<button>CONTACT US</button>
</form>
</div>
</div>
There appear to be numerous problems in your code.
First, you have form elements contained inside p elements. This is invalid HTML.
A paragraph element can contain only phrasing content. See this post and the spec.
Second, the string values of the grid-template-areas property must have the same number of columns. In your media query, the first row has two columns, and the second row has one column.
grid-template-areas: "cinema cinema" "why"
This is invalid CSS. The rule is ignored.
Try this instead:
grid-template-areas: "cinema cinema" "why ."
A period (.), or a sequence of contiguous periods (...), can be used to represent an empty grid area and maintain equal columns among strings.
See here for more details:
Grid areas not laying out properly in CSS Grid
grid-template-areas with ASCII art is not working

How permanently align div of a stacked element

I need to move all div inside of container up to a div above it
<div class="gb-box-holder">
<!-- GUIDE BOX -->
<div class="gb-box gb-box-1">
<div class="gb-header">
<span class="gb-decor-top"></span>
<div class="gb-logo">
<img class="gb-img" src="http://www.scim.si/wp-content/uploads/2015/01/apply.jpg" alt="">
<div class="gb-logo-cover"></div>
</div>
<h3>Lorem ipsum dolor</h3>
<!-- <span class="gb-decor-top"></span> -->
</div>
<div class="gb-container">
<span class="gb-decor-container"></span>
<p>
Lorem
</p>
<a class="gb-btn-guide" href="#"> Reed more</a>
</div>
</div>
<!-- GUIDE BOX -->
</div>
BOXES SECTION END -->
#gd-section .gb-box-holder {
display: flex;
display: -webkit-flex;
flex-wrap: wrap;
-webkit-flex-wrap: wrap;
justify-content: top;
-webkit-justify-content: top;
}
#gd-section .gb-box-holder .gb-box {
display: block;
width: 246px;
background-color: #303030;
margin: 5px;
float: left;
}
.gb-box class of each div
ps. Sorry for my spalling, English not my mother language
There are multiple ways You can approach this. The wrap that flex creates is only horizontal and not vertical - therefore, you won't be able to stack an item upwards. So it must be done in a column-wise manner. You just have to invert things in order for it to work like You want it to.
Here is a way to do this using Flex.
Another way of doing this is using HTML Columns which is your quickest option here but it will not be responsive in all browsers, therefore you will need to use prefixes and manual adjustments.
div {
-webkit-columns: 100px 3; /* Chrome, Safari, Opera */
-moz-columns: 100px 3; /* Firefox */
columns: 100px 3;
}
You can find a good tutorial on this here.
The other more fool-proof way is to use a plugin called CSS Masonry which uses JavaSript to align your items in a certain way. The only con here is that it will add a bit of js bulk to your code and it will be a bit time consuming. But it will be responsive and perfectly aligned.
If you decide to go along the CSS column path, this CodePen will do you good as well.
You can not achieve this with flexbox but you might want to try using css columns although they are meant to be used for text.
.gb-box-holder {
columns: 200px 3;
}
http://codepen.io/ingvi/pen/EgAZwz/