Is this layout remotely possible in IE11 (very crude example)?
$(document).on('click', '.js-toggle-hide', function(e){
e.preventDefault();
$(this).parent().parent().find('.js-hide').toggle();
});
#charset "UTF-8";
.c-sidebar {
display: grid;
grid-template-columns: 120px auto;
outline: 1px solid #ccc;
overflow: auto;
}
.c-cat {
display: grid;
grid-template-columns: 120px auto;
grid-template-rows: auto;
}
.c-cat__name {
grid-row: 1 / 1000;
}
.c-cat__toggle {
grid-row: 1 / 999;
min-width: 120px;
}
.c-cat__subcat {
grid-column: 3 / 4;
min-width: 120px;
}
.c-cat__subcat--all {
grid-column: 2 / 4;
}
/* decoration */
body {
padding: 15px;
background: #eee;
font-size: 11px;
}
.c-cell {
background: #fff;
outline: 1px solid #ccc;
padding: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="c-sidebar">
<div class="c-cell">All Categories</div>
<div>
<div class="c-cat">
<div class="c-cat__name c-cell">Sales</div>
<div class="c-cat__toggle c-cell">
All items
</div>
<div class="c-cat__subcat c-cell js-hide">Export sales</div>
<div class="c-cat__subcat c-cell js-hide">Other sales</div>
<div class="c-cat__subcat c-cell js-hide">Product sales</div>
<div class="c-cat__subcat--all c-cell js-hide"><b>All items</b></div>
</div>
</div>
</div>
Note that the number of items in the right columns is undefined (types of sales), client can add/remove them.
Are there any css tricks I'm not aware of?
The alternative is to use tables with complex js/jquery code (this is just a part of the code but it represents my dilemma perfectly) and that would be very tedious work.
My recommendation is if you want to be grid modern and still support something like IE11....then start with in display: flex and then do a media support to add your grid like this:
#supports (display: grid) {
#_your css grid here _#
}
So then you can add all your grid there....you are not necessarily repeating if you do this you are just doing the grid part here(grid-template, columns, rows, etc) and bypass any other styling like color, font, px and etc...
Related
I have a primary and a secondary headline.
The primary headline is longer and should be centered.
The second headline should start exactly where the first one starts.
So if this is my setup:
<h1 className="sofortcheck__headline--mobile">
Check your situation for free
</h1>
<h2 className="sofortcheck__subheader--mobile">
Only <span>2 minutes</span>
</h2>
I want both of those lines to start at exactly the same spot (on all devices) after I center the first line.
Is there a way to do this in pure CSS? So far I can only think of getting the left offset in JavaScript and then setting that for the second headline, but I feel like there should be a way to achieve this in CSS only.
When I center both elements the second one starts later than the first one because it's shorter.
When I use px margins it doesn't work for different screens.
This is fairly easy to do in the markup. You left-justify both the headline and subheadline in an element, then center that element relative to your page.
h1 { font-size: 0.75em; }
h2 { font-size: 0.5em; }
.headline-container {
display: flex;
}
.headline {
display: inline-block;
margin: 0 auto;
}
<div class="headline-container">
<div class="headline">
<h1>The primary headline which is longer and determines the centering.</h1>
<h2>The subheadline which is left-justified to the primary.</h2>
</div>
</div>
CSS-Grid can do that.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
::before,
::after {
box-sizing: inherit;
}
body {
display: grid;
grid-template-columns: 1fr auto 1fr;
position: relative;
align-items: center;
}
body::before {
content: "";
position: absolute;
left: 50%;
height: 100vh;
width: 1px;
background: green;
}
.sofortcheck__headline--mobile {
grid-column: 2;
border: 1px solid red;
}
.sofortcheck__subheader--mobile {
grid-column: 2;
grid-row: 2;
border: 1px solid grey;
}
<h1 class="sofortcheck__headline--mobile">
Check your situation for free
</h1>
<h2 class="sofortcheck__subheader--mobile">
Only <span>2 minutes</span>
</h2>
I'm trying to achieve this layout (https://codepen.io/totkeks/pen/PowodPq) with a top section, main section and side section.
<div class="grid">
<div class="top">Top</div>
<div class="main">Main</div>
<div class="side">Side</div>
</div>
body {
padding: 0;
margin: 0;
}
.grid {
display: grid;
grid-gap: 3rem;
grid-template-columns: 22rem minmax(48rem, auto);
grid-auto-rows: auto;
padding: 3rem;
min-height: 100vh;
box-sizing: border-box;
border: 2px dotted black;
}
.top, .main, .side {
background-color: papayawhip;
}
.main {
grid-row: span 2;
}
#media screen and (max-width: 1200px) {
.grid {
grid-template-columns: 1fr;
}
}
When the page is smaller (< 1280px currently in CSS query) the three sections are stacked on top of each other, first top, then main, then side, all covering the full width.
When the page is wider, the top and side sections are fixed size on the left side and the main section is on the right side, growing as space becomes available.
Just a moment ago I found this Q&A Responsive layout without media query and while it goes in the right direction, it is not entirely what I'm trying to achieve.
I already spent two evenings with this idea and would like to find a solution or get a definitive "No, that's not possible with current CSS".
You could give a try with auto-fit, grid-colum, grid-row and use width + calc() to trick the wrapping . But you could find funny behaviors from a browser to anoter . (auto-flow is required ) However, mediaquerie is made for this, much cleaner and reliable.
body {
padding: 0;
margin: 0;
}
.grid {
display: grid;
grid-gap: 3rem;
margin: 1em;
border: solid;
grid-template-columns: repeat(auto-fit, minmax(22rem,auto));
grid-auto-rows: auto;
padding: 3rem;
min-height: calc(100vh - 2em);
box-sizing: border-box;
}
.top,
.main,
.side {
background-color: orange;
border:solid;
}
.top,
.side {
grid-column: 1;
width: 22rem;
min-width:100%;
}
.main {
grid-column: auto;
min-width: calc(100vw - 33rem);
grid-row: span 2;
}
<div class="grid">
<div class="top">Top</div>
<div class="main">Main</div>
<div class="side">Side</div>
</div>
My answer maybe yes for the fun only.
I don't understand why DIV 3 is not the same size as DIV 1 + DIV 2.
https://codepen.io/anon/pen/vaVqPW
.grid {
display: grid;
grid-auto-columns: 1fr 1fr; /* I also tried 50% 50% */
grid-gap: 20px;
}
Firefox 61 should support css grid according to caniuse
https://caniuse.com/#feat=css-grid
* {
box-sizing: border-box;
}
.grid {
display: grid;
grid-auto-columns: 1fr 1fr;
grid-gap: 20px;
}
.content {
grid-column: 1;
background: red;
}
.sidebar {
grid-column: 2;
background: blue;
}
.grid>* {
/*border: 1px dashed red; */
/* demo only */
}
.box {
width: 50%;
height: 75px;
background-color: black;
color: #fff;
padding: 20px;
position: relative;
float: left;
}
.box100 {
width: 100%;
height: 75px;
color: #fff;
padding: 20px;
}
.box.arrow-left:after {
content: " ";
position: absolute;
left: -15px;
margin-top: -15px;
top: 50%;
border-top: 15px solid transparent;
border-right: 15px solid black;
border-left: none;
border-bottom: 15px solid transparent;
}
<div class="grid">
<div class="content">
<div class="box" style="background:gray">
DIV 1 (50% of column 1)
</div>
<div class="box arrow-left">
DIV 2 (50% of column 1)
</div>
</div>
<div class="sidebar">
<div class="box100">DIV 3 (100% of column 2)</div>
</div>
</div>
<div>
<div class="content" style="background:tomato">
<p>content 4 (100% of column 1 + GAP + 100% of column 2 )</p>
</div>
</div>
Firefox does indeed support CSS Grid (see caniuse.com).
The problem is that Firefox does not appear to support multiple values in grid-auto-columns.
This is your code in Chrome. No problems.
This is your code in Firefox. There's a problem. The code is invalid / not recognized.
It fails in Firefox here, too:
The grid-auto-columns property can take multiple values, per the spec definition. However, Firefox appears to lack support for this set-up. It only accepts a single value.
Your correction to the problem, as stated in your answer and copied below, is simply to switch from implicit columns (grid-auto-columns) to explicit columns (grid-template-columns).
grid: auto-flow dense / 1fr 1fr;
The grid property is a shorthand property that allows you to set all explicit and implicit rules in a single declaration. Your rule above breaks down to this:
So in the end, it appears that a simple switch from grid-auto-columns to grid-template-columns was all you needed.
grid: auto-flow dense / 1fr 1fr;
this seems to solve the Problem!
At the same time deleting the line:
grid-auto-columns: 1fr 1fr;
Pen is updated: https://codepen.io/anon/pen/vaVqPW
I'd like to have a bottom border on my title that breaks the grid. There are 3 columns, left, middle, and right, and my title and content go in the middle. I'd like to have a bottom border extend all the way to the left side of the left column. Is there a better way to do this than what I came up with below? Does CSS grid provide a built-in mechanism for doing this sort of thing? I'd appreciate any suggestions.
.grid-container {
padding: 10px;
display: grid;
grid-template-columns: [start] 1fr [middle] 4fr [end] 1fr ;
grid-gap: 1rem;
background-color: #fff;
color: #444;
}
.start {
grid-column: start;
background-color: #ccc;
}
.middle {
grid-column: middle;
}
.title {
}
.title:after {
content: '';
display: block;
border-bottom: 1px solid red;
margin-left: calc(-25% - 1rem);
}
.end {
grid-column: end;
background-color: #ccc;
}
<div class="grid-container">
<div class="start">Start</div>
<div class="middle">
<h2 class="title">My Title</h2>
<div class="content">Some text lorem ipsum, whatever.</div>
</div>
<div class="end">End</div>
</div>
This is a modification of Michael_B's answer above. Seems to work the same but without the addition of markup to the original html.
.grid-container {
padding: 10px;
display: grid;
grid-template-columns: [start] 1fr [middle] 4fr [end] 1fr ;
grid-template-rows: repeat(100, 1px); /* new */
grid-column-gap: 1rem; /* adjusted; removed grid-row-gap */
background-color: #fff;
color: #444;
}
.start {
grid-column: start;
background-color: #ccc;
grid-row: 1 / -1; /* new */
}
.middle {
grid-column: middle;
grid-row: 1 / -1; /* new */
}
.end {
grid-column: end;
background-color: #ccc;
grid-row: 1 / -1; /* new */
}
.grid-container:after { /* new */
content: '';
background-color: red;
grid-row-start: 47;
grid-column: 1 / 3;
}
<div class="grid-container">
<div class="start">Start</div>
<div class="middle">
<h2 class="title">My Title</h2>
<div class="content">Some text lorem ipsum, whatever.</div>
</div>
<div class="end">End</div>
</div>
Your negative margin method seems to work. It's a bit clunky, but seems effective nonetheless.
You could also use absolute positioning to align that border under the title. The container would be the bounding box (i.e., position: relative). But that's also a bit clunky.
If you want a pure grid solution, that's also possible. The method I came up with is clean and effective. Some may consider it overkill for a simple border, but your need is somewhat unique, so this may be useful.
Here's the basic concept:
Divide your container into 100 tiny rows (1px).
Make your existing grid items span these rows from top to bottom.
Now you're back to your original layout, but with an upgrade under the hood.
You now have 100 places for a border line.
Create a new grid item (either DOM or pseudo-element).
Span the item across the row under your title.
VoilĂ ! :-)
.grid-container {
padding: 10px;
display: grid;
grid-template-columns: [start] 1fr [middle] 4fr [end] 1fr ;
grid-template-rows: repeat(100, 1px); /* new */
grid-column-gap: 1rem; /* adjusted; removed grid-row-gap */
background-color: #fff;
color: #444;
}
.start {
grid-column: start;
background-color: #ccc;
grid-row: 1 / -1; /* new */
}
.middle {
grid-column: middle;
grid-row: 1 / -1; /* new */
}
.end {
grid-column: end;
background-color: #ccc;
grid-row: 1 / -1; /* new */
}
.grid-container::after { /* new */
content: "";
background-color: red;
grid-row-start: 47;
grid-column: 1 / 3;
}
<div class="grid-container">
<div class="start">Start</div>
<div class="middle">
<h2 class="title">My Title</h2>
<div class="content">Some text lorem ipsum, whatever.</div>
</div>
<div class="end">End</div>
<div class="border"></div>
</div>
jsFiddle demo
Another method, based on the same idea as Micheael_B had, "you need more rows".
What you can do is split the middle part in 3 parts. Title, border, content.
You can give each their own grid-row in order.
See fiddle that only works in Firefox because instead of unwrapping the 3 tags I used the display property contents
https://jsfiddle.net/npddveag/2/
The display property contents is a magic way of making the wrapper div disappear without the actual markup disappearing.(and inherited styles will stil apply, so there is a bit more to it).
If you need it to work in other browsers you can just unwrap the 3 tags.
I'm experimenting with CSS Grids, and this is the layout I'm building:
.grid {
display: grid;
align-items: center;
grid-template-columns: 1fr 4rem 1fr;
grid-template-rows: 1rem 1fr 1rem;
max-width: 900px;
margin: 0 auto;
}
.text {
/*
// Ideally, this should be
grid-area: text
*/
grid-column: 1 / 3;
grid-row: 2 / 3;
/* Fix z-index */
position: relative;
padding: 4rem;
background-color: #fff;
}
.image {
/*
// Ideally, this should be
grid-area: image;
*/
grid-column: 2 / 4;
grid-row: 1 / -1;
background-color: lightgray;
padding: 1rem;
/* Center das image */
display: flex;
justify-content: center;
}
/* Basic body */
body {
background-color: #fafafa;
font-family: sans-serif;
padding: 2rem;
}
img {
max-width: 100%;
height: auto;
}
<div class="grid">
<div class="text">One morning, when bobby woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. He lay on his leg like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into
stiff sections.
</div>
<div class="image">
<img src="http://unsplash.it/400/400" />
</div>
</div>
(best to preview in full page...)
What I'd like to avoid:
.text and .image both currently are using grid-column: * / *; syntax, instead I'd like to use grid-area: text and grid-area: image;.
Is it possible to define grid-template-{columns|rows} as overlapping areas? I tried using second way of defining grid areas
, but that didn't seem to work.
Looks like you can't do [a-start] [b-start] [a-end] [b-end] in that syntax, or at least I didn't manage to.
So - Is there any way to create an overlapping grid using named areas?
I'm trying to use the named areas for convenience purely - so that it's easier to reason about the responsive layout code, instead of repeating myself multiple times in media queries.
Edit
Found the answer because of #vals answer below.
This seemed to work just fine, I probably made a syntax error in my previous attempt somewhere:
grid-template-columns: [text-start] 1fr [image-start] 4rem [text-end] 1fr [image-end];
grid-template-rows: [image-start] 1rem [text-start] 1fr [text-end] 1rem [image-end];
At least in a more basic layout, it seems to work for me:
.container {
border: solid 1px green;
height: 180px;
width: 300px;
display: grid;
grid-template-columns: [left-start] 100px [right-start] 100px [left-end] 100px [right-end];
grid-template-rows: [left-start] 60px [right-start] 60px [left-end] 60px [right-end];
}
.left {
grid-area: left;
background-color: red;
}
.right {
grid-area: right;
background-color: lightgray;
opacity: 0.5;
}
<div class="container">
<div class="left">
</div>
<div class="right">
</div>
</div>