I'm using following HTML markup for my grid.
<section class="grid">
<article class="grid-item width-2x height-2x">....</article>
<article class="grid-item">....</article>
<article class="grid-item">....</article>
<article class="grid-item width-2x">....</article>
<article class="grid-item height-2x">....</article>
<article class="grid-item">....</article>
<article class="grid-item">....</article>
<article class="grid-item width-2x height-2x">....</article>
</section>
The SCSS code is something like below:
.grid {
display: grid;
grid-template-columns: repeat( 4, 1fr );
grid-gap: 30px;
align-items: start;
.grid-item {
&.height-2x {
grid-row: span 2;
}
&.width-2x {
grid-column: span 2;
}
}
}
Since I'm using auto-prefixer in my workflow it automatically adds all relevant properties with -ms prefix. I can confirm it via inspect element.
Now, the issue is this code works just fine in Chrome, Firefox and Opera, but when I open this page in Microsoft Edge or in IE 11 all grid items are overlapping each other at first cell. According to this site these browsers support CSS Grid layout with -ms prefix. I've created a CodePen for this scenario.
CodePen Link
Why is it not working?
.grid {
display: -ms-grid;
display: grid;
-ms-grid-columns: (1fr)[4];
grid-template-columns: repeat(4, 1fr);
-ms-grid-rows: (270px)[4];
grid-template-rows: repeat(4, 270px);
grid-gap: 30px;
}
.grid .grid-item {
background-color: #000;
color: #fff;
text-align: center;
line-height: 270px;
}
.grid .grid-item.height-2x {
-ms-grid-row: span 2;
grid-row: span 2;
}
.grid .grid-item.width-2x {
-ms-grid-column: span 2;
grid-column: span 2;
}
<section class="grid">
<article class="grid-item width-2x height-2x">....</article>
<article class="grid-item">....</article>
<article class="grid-item">....</article>
<article class="grid-item width-2x">....</article>
<article class="grid-item height-2x">....</article>
<article class="grid-item">....</article>
<article class="grid-item">....</article>
<article class="grid-item width-2x height-2x">....</article>
</section>
IE11 uses an older version of the Grid specification.
The properties you are using don't exist in the older grid spec. Using prefixes makes no difference.
Here are three problems I see right off the bat.
repeat()
The repeat() function doesn't exist in the older spec, so it isn't supported by IE11.
You need to use the correct syntax, which is covered in another answer to this post, or declare all row and column lengths.
Instead of:
.grid {
display: -ms-grid;
display: grid;
-ms-grid-columns: repeat( 4, 1fr );
grid-template-columns: repeat( 4, 1fr );
-ms-grid-rows: repeat( 4, 270px );
grid-template-rows: repeat( 4, 270px );
grid-gap: 30px;
}
Use:
.grid {
display: -ms-grid;
display: grid;
-ms-grid-columns: 1fr 1fr 1fr 1fr; /* adjusted */
grid-template-columns: repeat( 4, 1fr );
-ms-grid-rows: 270px 270px 270px 270px; /* adjusted */
grid-template-rows: repeat( 4, 270px );
grid-gap: 30px;
}
Older spec reference:
https://www.w3.org/TR/2011/WD-css3-grid-layout-20110407/#grid-repeating-columns-and-rows
span
The span keyword doesn't exist in the older spec, so it isn't supported by IE11. You'll have to use the equivalent properties for these browsers.
Instead of:
.grid .grid-item.height-2x {
-ms-grid-row: span 2;
grid-row: span 2;
}
.grid .grid-item.width-2x {
-ms-grid-column: span 2;
grid-column: span 2;
}
Use:
.grid .grid-item.height-2x {
-ms-grid-row-span: 2; /* adjusted */
grid-row: span 2;
}
.grid .grid-item.width-2x {
-ms-grid-column-span: 2; /* adjusted */
grid-column: span 2;
}
Older spec reference:
https://www.w3.org/TR/2011/WD-css3-grid-layout-20110407/#grid-row-span-and-grid-column-span
grid-gap
The grid-gap property, as well as its long-hand forms grid-column-gap and grid-row-gap, don't exist in the older spec, so they aren't supported by IE11. You'll have to find another way to separate the boxes. I haven't read the entire older spec, so there may be a method. Otherwise, try margins.
grid item auto placement
There was some discussion in the old spec about grid item auto placement, but the feature was never implemented in IE11. (Auto placement of grid items is now standard in current browsers).
So unless you specifically define the placement of grid items, they will stack in cell 1,1.
Use the -ms-grid-row and -ms-grid-column properties.
CSS Grid auto placement in IE/EDGE
CSS Grid not working in ie11 despite prefixes
https://www.w3.org/TR/2011/WD-css3-grid-layout-20110407/#automatic-placement-of-grid-items
Michael has given a very comprehensive answer, but I'd like to point out a few things which you can still do to be able to use grids in IE in a nearly painless way.
The repeat functionality is supported
You can still use the repeat functionality, it's just hiding behind a different syntax. Instead of writing repeat(4, 1fr), you have to write (1fr)[4]. That's it.
See this series of articles for the current state of affairs: https://css-tricks.com/css-grid-in-ie-debunking-common-ie-grid-misconceptions/
Supporting grid-gap
Grid gaps are supported in all browsers except IE. So you can use the #supports at-rule to set the grid-gaps conditionally for all new browsers:
Example:
.grid {
display: grid;
}
.item {
margin-right: 1rem;
margin-bottom: 1rem;
}
#supports (grid-gap: 1rem) {
.grid {
grid-gap: 1rem;
}
.item {
margin-right: 0;
margin-bottom: 0;
}
}
It's a little verbose, but on the plus side, you don't have to give up grids altogether just to support IE.
Use Autoprefixer
I can't stress this enough - half the pain of grids is solved just be using autoprefixer in your build step. Write your CSS in a standards-complaint way, and just let autoprefixer do it's job transforming all older spec properties automatically. When you decide you don't want to support IE, just change one line in the browserlist config and you'll have removed all IE-specific code from your built files.
The answer has been given by Faisal Khurshid and Michael_B already.
This is just an attempt to make a possible solution more obvious.
For IE11 and below you need to enable grid's older specification in the parent div e.g. body or like here "grid" like so:
.grid-parent{display:-ms-grid;}
then define the amount and width of the columns and rows like e.g. so:
.grid-parent{
-ms-grid-columns: 1fr 3fr;
-ms-grid-rows: 4fr;
}
finally you need to explicitly tell the browser where your element (item) should be placed in e.g. like so:
.grid-item-1{
-ms-grid-column: 1;
-ms-grid-row: 1;
}
.grid-item-2{
-ms-grid-column: 2;
-ms-grid-row: 1;
}
To support IE11 with auto-placement, I converted grid to table layout every time I used the grid layout in 1 dimension only. I also used margin instead of grid-gap.
The result is the same, see how you can do it here https://jsfiddle.net/hp95z6v1/3/
Related
I have made up a grid layout that consists of 3 columns wide and 3 rows tall:
.home-works {
padding: 30px;
font-size: 1.2rem;
display: grid;
grid-template-columns: 2fr 2fr 2fr;
grid-template-rows: 2fr 4fr 4fr;
grid-gap: 10px;
}
This is giving me zero problems at desktop view, but what I need to follow up with, now, is when the view port breaks, at the moment I'm working with a max-width:768px rule. So, right now, once the view port breaks to that max-width, any CSS Grid command doesn't seem to have an effect or a change. I have tried using grid-row or grid-row-start grid-column or grid-row-start but no luck.
This is my HTML for the layout:
<div class="home-works">
<div class="head">
<h1>Let's stay connected!</h1>
</div>
<div class="col-menu">
<img class="image-home" src="img/profile-picture.png" width="50%">
<ul>
<li>home</li>
<li>about</li>
<li>contact</li>
<li>downloads</li>
</ul>
</div>
<div class="main-content">
<p>This is my website and I call it, the <em>"glassless window"</em>
Why? Because using the frame on your device (mobile, desktop or laptop)
we are allowed to establish a connection thus enabling me to show you my
up and coming projects. </p>
</div>
<div class="caption-object">
<p>I really wish you could <a class="drop-a-line-link" href="#">drop me a line</a> somewhere
in the future!</p>
</div>
</div>
And this is the CSS for the distribution:
.head {
grid-column: 1 / 4;
text-align: center;
}
.col-menu {
grid-column: 1;
grid-row: 2 / 3;
}
.main-content {
grid-column: 2 / 4;
grid-row: 2 / 3;
}
.caption-object {
grid-column: 3 / 4;
grid-row: 3;
}
This is my first time going about media queries and CSS Grid, meaning this is the first time i input a grid command inside a media query rule set. I checked to see if this would happen too if I wanted to change the background-color: plum; and it did worked. I know about repeat(minmax()) but honestly I wouldn't know how to properly achieve the same look or if it would have the same 'layout design' because then I'd have to delete the grid row's and column's placement? Like I said this is my first time ever using CSS Grid with media queries, I have attached some pics, thanks!
Initially I decided not to include it because nothing had seemed to be working so I didn't have a reason to include.
#media only screen and (max-width: 768px) {
.nav-items {
flex-direction: column;
align-items: center;
}
.navbar {
height: 200px;
padding-bottom: 20px;
}
.footer-link {
align-self: center;
left: 0;
top: 0;
}
.main-container {
flex-flow: column wrap;
margin: 0 10px;
}
.drop-a-line-link {
text-decoration: underline wavy;
}
}
Media Query
To answer my own question this is what I did and its available on MDN, have to check "Redefining the grid using media queries" topic.
To reorganize a CSS Grid layout one must set up the media query rule (which in this case I had it different than on MDN archives but somehow still worked) and in there I had to reassign my grid-template-areas, which was also another thing I lacked, I was NOT using grid-areas, I had stuff like grid-row or grid-columns. Apparently this seems to be a huge factor that comes to play when we are inside our Media Query code. One thing that they do note as important, when working with grid-areas is that one should assign them, outside of any Media Query commands, to cover just one "row" or one "column", I guess depends on your current grid-auto-flow command, which at default is set as row while defining the columns and rows
So, mine is looking like this:
display: grid;
grid-template-columns: 1fr;
grid-template-rows: minmax(350px, auto);
grid-template-areas:
"header"
"menu"
"main"
"caption";
Since I had not defined any areas on my previous grid I would never have gotten it to work the way I intended for it to behave. Well, and then once in the MQ, you assign the grid as best you can, but first, you need to use grid-template-areas to re-assign the areas, and as well as your columns, using grid-template-columns, this depends on your layout and item sizes or basically it depends on the idea that you had for the grid.
So my Media Query code ended up looking like this:
#media (min-width: 500px) {
.home-works {
grid-template-columns: 2fr 2fr 2fr;
grid-template-areas:
"header header menu"
". main main"
". . caption";
}
}
#media (min-width:700px) {
.home-works {
grid-template-areas:
"header header header"
"menu main main"
". . caption";
}
}
Important: the "." are "white-space", or "negative space" or "empty cells".
Currently I'm checking my website in all browsers and found a problem. Normally this tabs should looks like this:
But when I open the page in the IE it looks like this:
I've checked the DOM and B is under A. I've did it like described in the CSS documentation but it's not working. This is my CSS for this tab:
ul.tabs {
display: grid;
display: -ms-grid;
grid-template-columns: 1fr 1fr;
-ms-grid-columns: 1fr 1fr;
}
IE/Edge 10-15 support an older version of the CSS-grid spec.
Among other things, auto-placement is missing.
https://rachelandrew.co.uk/archives/2016/11/26/should-i-try-to-use-the-ie-implementation-of-css-grid-layout has a list of differences.
You need
ul.tabs #tab1 {
-ms-grid-row: 1;
-ms-grid-column: 1;
}
ul.tabs #tab2 {
-ms-grid-row: 1;
-ms-grid-column: 2;
}
I'm using following HTML markup for my grid.
<section class="grid">
<article class="grid-item width-2x height-2x">....</article>
<article class="grid-item">....</article>
<article class="grid-item">....</article>
<article class="grid-item width-2x">....</article>
<article class="grid-item height-2x">....</article>
<article class="grid-item">....</article>
<article class="grid-item">....</article>
<article class="grid-item width-2x height-2x">....</article>
</section>
The SCSS code is something like below:
.grid {
display: grid;
grid-template-columns: repeat( 4, 1fr );
grid-gap: 30px;
align-items: start;
.grid-item {
&.height-2x {
grid-row: span 2;
}
&.width-2x {
grid-column: span 2;
}
}
}
Since I'm using auto-prefixer in my workflow it automatically adds all relevant properties with -ms prefix. I can confirm it via inspect element.
Now, the issue is this code works just fine in Chrome, Firefox and Opera, but when I open this page in Microsoft Edge or in IE 11 all grid items are overlapping each other at first cell. According to this site these browsers support CSS Grid layout with -ms prefix. I've created a CodePen for this scenario.
CodePen Link
Why is it not working?
.grid {
display: -ms-grid;
display: grid;
-ms-grid-columns: (1fr)[4];
grid-template-columns: repeat(4, 1fr);
-ms-grid-rows: (270px)[4];
grid-template-rows: repeat(4, 270px);
grid-gap: 30px;
}
.grid .grid-item {
background-color: #000;
color: #fff;
text-align: center;
line-height: 270px;
}
.grid .grid-item.height-2x {
-ms-grid-row: span 2;
grid-row: span 2;
}
.grid .grid-item.width-2x {
-ms-grid-column: span 2;
grid-column: span 2;
}
<section class="grid">
<article class="grid-item width-2x height-2x">....</article>
<article class="grid-item">....</article>
<article class="grid-item">....</article>
<article class="grid-item width-2x">....</article>
<article class="grid-item height-2x">....</article>
<article class="grid-item">....</article>
<article class="grid-item">....</article>
<article class="grid-item width-2x height-2x">....</article>
</section>
IE11 uses an older version of the Grid specification.
The properties you are using don't exist in the older grid spec. Using prefixes makes no difference.
Here are three problems I see right off the bat.
repeat()
The repeat() function doesn't exist in the older spec, so it isn't supported by IE11.
You need to use the correct syntax, which is covered in another answer to this post, or declare all row and column lengths.
Instead of:
.grid {
display: -ms-grid;
display: grid;
-ms-grid-columns: repeat( 4, 1fr );
grid-template-columns: repeat( 4, 1fr );
-ms-grid-rows: repeat( 4, 270px );
grid-template-rows: repeat( 4, 270px );
grid-gap: 30px;
}
Use:
.grid {
display: -ms-grid;
display: grid;
-ms-grid-columns: 1fr 1fr 1fr 1fr; /* adjusted */
grid-template-columns: repeat( 4, 1fr );
-ms-grid-rows: 270px 270px 270px 270px; /* adjusted */
grid-template-rows: repeat( 4, 270px );
grid-gap: 30px;
}
Older spec reference:
https://www.w3.org/TR/2011/WD-css3-grid-layout-20110407/#grid-repeating-columns-and-rows
span
The span keyword doesn't exist in the older spec, so it isn't supported by IE11. You'll have to use the equivalent properties for these browsers.
Instead of:
.grid .grid-item.height-2x {
-ms-grid-row: span 2;
grid-row: span 2;
}
.grid .grid-item.width-2x {
-ms-grid-column: span 2;
grid-column: span 2;
}
Use:
.grid .grid-item.height-2x {
-ms-grid-row-span: 2; /* adjusted */
grid-row: span 2;
}
.grid .grid-item.width-2x {
-ms-grid-column-span: 2; /* adjusted */
grid-column: span 2;
}
Older spec reference:
https://www.w3.org/TR/2011/WD-css3-grid-layout-20110407/#grid-row-span-and-grid-column-span
grid-gap
The grid-gap property, as well as its long-hand forms grid-column-gap and grid-row-gap, don't exist in the older spec, so they aren't supported by IE11. You'll have to find another way to separate the boxes. I haven't read the entire older spec, so there may be a method. Otherwise, try margins.
grid item auto placement
There was some discussion in the old spec about grid item auto placement, but the feature was never implemented in IE11. (Auto placement of grid items is now standard in current browsers).
So unless you specifically define the placement of grid items, they will stack in cell 1,1.
Use the -ms-grid-row and -ms-grid-column properties.
CSS Grid auto placement in IE/EDGE
CSS Grid not working in ie11 despite prefixes
https://www.w3.org/TR/2011/WD-css3-grid-layout-20110407/#automatic-placement-of-grid-items
Michael has given a very comprehensive answer, but I'd like to point out a few things which you can still do to be able to use grids in IE in a nearly painless way.
The repeat functionality is supported
You can still use the repeat functionality, it's just hiding behind a different syntax. Instead of writing repeat(4, 1fr), you have to write (1fr)[4]. That's it.
See this series of articles for the current state of affairs: https://css-tricks.com/css-grid-in-ie-debunking-common-ie-grid-misconceptions/
Supporting grid-gap
Grid gaps are supported in all browsers except IE. So you can use the #supports at-rule to set the grid-gaps conditionally for all new browsers:
Example:
.grid {
display: grid;
}
.item {
margin-right: 1rem;
margin-bottom: 1rem;
}
#supports (grid-gap: 1rem) {
.grid {
grid-gap: 1rem;
}
.item {
margin-right: 0;
margin-bottom: 0;
}
}
It's a little verbose, but on the plus side, you don't have to give up grids altogether just to support IE.
Use Autoprefixer
I can't stress this enough - half the pain of grids is solved just be using autoprefixer in your build step. Write your CSS in a standards-complaint way, and just let autoprefixer do it's job transforming all older spec properties automatically. When you decide you don't want to support IE, just change one line in the browserlist config and you'll have removed all IE-specific code from your built files.
The answer has been given by Faisal Khurshid and Michael_B already.
This is just an attempt to make a possible solution more obvious.
For IE11 and below you need to enable grid's older specification in the parent div e.g. body or like here "grid" like so:
.grid-parent{display:-ms-grid;}
then define the amount and width of the columns and rows like e.g. so:
.grid-parent{
-ms-grid-columns: 1fr 3fr;
-ms-grid-rows: 4fr;
}
finally you need to explicitly tell the browser where your element (item) should be placed in e.g. like so:
.grid-item-1{
-ms-grid-column: 1;
-ms-grid-row: 1;
}
.grid-item-2{
-ms-grid-column: 2;
-ms-grid-row: 1;
}
To support IE11 with auto-placement, I converted grid to table layout every time I used the grid layout in 1 dimension only. I also used margin instead of grid-gap.
The result is the same, see how you can do it here https://jsfiddle.net/hp95z6v1/3/
I am new to CSS in general and trying out a simple grid layout. This is what I have.
CSS
.layoutGrid {
display: grid;
grid-gap: 10px;
grid-auto-rows: minMax(100px, auto);
}
.articleCard {
display: grid;
grid-template-rows: 100px 300px 100px;
grid-template-areas: "article-title"
"article-body"
"article-footer";
grid-auto-flow: row dense;
}
.articleHeader {
grid-area: article-title;
}
.articleBody {
grid-area: article-body;
}
.articleFooter {
display: grid;
grid-template-columns: 0.5fr 0.5fr;
grid-template-areas: "articleDomain articleKeypoints";
grid-area: article-footer;
grid-auto-flow: row dense;
}
.articleKeypoints {
grid-area: article-keypoints;
}
.articleDomain {
grid-area: article-domain;
}
#media only screen and (min-width: 600px) {
.layoutGrid {
grid-template-columns: repeat(3, 1fr);
}
}
#media only screen and (max-width: 600px) {
.layoutGrid {
grid-template-columns: repeat(1, 1fr);
}
}
HTML
<div id="mainContent" className="container layoutGrid">
<Card className={"articleCard"} style={{height:"500px", flex: "1 1 auto", padding: "1.25rem", boxSizing: "border-box"}}>
<CardHeader className="articleHeader">
<CardTitle>{props.articleDetails.Title}</CardTitle>
</CardHeader>
<CardBody className="articleBody">
<CardText>{props.articleDetails.Summary}</CardText>
</CardBody>
<div className="row articleFooter">
<div className="col-auto mr-auto">
<Button outline color="info">Read Keypoints</Button>
</div>
<div className="col-auto">
<CardSubtitle style={{verticalAlign: 'text-bottom'}}>
<small>{props.articleDetails.Domain}</small>
</CardSubtitle>
</div>
</div>
</Card>
</div>
There is nothing here which adds a ::before element, but in the result the first element of the grid is always a ::before element. Even the inner grid which says "Read Keypoints" has the same issue. The outer layout is in a loop but I dont think that would affect anything.
Can anyone tell how do I get around this, and also any pointers on how to improve the overall structure of the layout would be really appreciated!
Writing my comment as an answer as it seems to do the trick.
That's bootstrap.css its .container selector that adds the before and
after. If you're using grid you should either not user the class
container here (some other name) or not use bootstrap.
There is nothing wrong with ::before or ::after. Those are CSS pseudo elements/selectors that inserts something before/after the content of each selected element(s).
Here they are shown because of viewing the code dynamically in Developers tool of the browser.
Just compare it with the real source of the page - right click on the page and select View page source (the message vary in web browsers). A blank tab will appear with exact code as it was send from the server to the web browser.
Slightly related to my question here.
Say in Sass, if I wish to use multiple values for one property, is there a way that I can achieve this using a mixin?
NB: I know that my usage of #each is wrong but this helps to illustrate what I'm trying to do.
So far I have the following
#mixin grid-fractions($grid-type, $args) {
#supports (display:grid) {
display: grid;
#{$grid-type}: #each $args #{$args}fr;
}
}
It's usage is as follows: #include('grid-template-rows', 2, 1, 1); And I'd like to get the mixin to output something like this:
#supports (display:grid) {
display: grid;
grid-template-rows: 2fr 1fr 1fr;
}
I know that $args lets you include multiple values in a mixin but it's obviously not working as I'm probably not using it correctly!
Why not just #include('grid-template-rows', '2fr 1fr 1fr'); ?
Or
Include a mixin and pass parameters as an arglist. It can be done different ways depending on what you want.
#mixin grid($template-rows:null,$template-cols:null,$template-areas:null){
#supports (display:grid) {
display:grid;
$grid-rows:();
$grid-cols:();
$grid-areas:();
#each $rows in $template-rows{
$grid-rows: append($grid-rows, #{$rows}fr);
}
#each $cols in $template-cols{
$grid-cols: append($grid-cols, #{$cols}fr);
}
#each $areas in $template-areas{
$grid-areas: append($grid-areas, #{$areas}fr);
}
grid-template-rows:#{$grid-rows};
grid-template-columns:#{$grid-cols};
grid-template-areas:#{$grid-areas};
}
}
html{
#include grid(1 2 3, 4 5 6, 7 8 9 );
}
/*
// Outputs:
#supports (display: grid) {
html {
display:grid;
grid-template-rows: 1fr 2fr 3fr;
grid-template-columns: 4fr 5fr 6fr;
grid-template-areas: 7fr 8fr 9fr;
}
}
*/