I have a special css grid layout that is based on completely square grid boxes that are defined like this:
grid-template-columns: repeat(5, minmax(200px, 20vw));
grid-auto-rows: minmax(200px, 20vw);
grid-template-areas:
"branding nav nav . meta"
". title title featured-image ."
". primary primary featured-image ."
". secondary secondary featured-image ."
". footer footer . .";
problem is that I need to have a content area within this grid that is flexible. By default it spans 2 columns and 2 rows. The content area is outlined in red:
I would like the layout to make it possible for the content area to span for example 2 columns and 4 rows for example. Basically 2-n rows based on the content.
Is there any smart way of doing this?
I did something similar for a HomePage, but using JavaScript not just CSS grid:
A card grid ocupying 2 rows only if the contents overflow the container.
static expandIfActive(card){
const content = card.querySelector('.content')
const body = card.querySelector('.card-body')
return body.clientHeight - options.clientHeight - (#margins and paddings) == 0
}
If the content matches the heigth of the container means it's overflowing, so I add the property grid-row: span 2
Related
See this fiddle.
Consider a grid of words in four columns, with each column being the same width. I can get this with grid-template-columns: repeat(auto-fill, minmax(25%, 1fr)); Most of the time, these will be short words. But there could be a long word which overflows its block:
If this were static data, I could have just changed the grid css to grid-template-columns: repeat(auto-fill, minmax(33%, 1fr)); to comfortably fill the space:
How can I make the CSS renderer adjust the number of columns for me, making each the same width, using the width of the widest word block in the set?
I'm surprised that CSS doesn't (as far as I can tell) support this since I think it should be a common use case for wrapping grids. I tinkered until I had a solution with a minimal amount of javascript:
example fiddle with IIFE
First, we need to find out how wide the widest string (or could be any block element) will be when rendered on the client. grid-template-columns: repeat(1, max-content); will do that by arranging the elements in a single column, and all elements get the width of the widest one. After the dimensions are established but before being rendered to the screen, grab any element, compute the number of columns that will fit, then change the CSS for the container to have that many columns + 1fr to make them fill the space:
(function(){
const ul = document.querySelectorAll('ul')[0];
const ee = [...document.querySelectorAll('li')];
const max = ee.map(e=>e.offsetWidth).reduce((a,b)=>Math.max(a, b));
const cols = Math.min(5,Math.floor(ul.offsetWidth/max));
ul.style.gridTemplateColumns = "repeat("+cols+", 1fr)";
})();
This seems to work with no flicker in all evergreen browsers. Angular version I used:
ngAfterViewInit(): void {
const ul: HTMLElement = this.ul.nativeElement;
let cols: number = 0;
const w: number = ul.children[0].clientWidth;
if (w > 0) {
cols = Math.min(5, Math.floor(ul.offsetWidth / w));
}
ul.style.gridTemplateColumns = "repeat(" + cols + ",1fr)";
}
As far as I know this is unsolvable with CSS-only, so, I will provide a Javascript-based solution.
First of all, let's find the longest text:
let longestText = '';
for (let text of texts) {
if (longestText.length < text.length) longestText = text;
}
Then, you can find that item:
let lng = document.querySelectorAll('ul li').filter((item) => item.innerText === longestText)[0].offsetWidth;
Then you can divide the whole width that you have at your disposal with lng, the value you have just calculated and see how many columns you can have.
I am using CSS Grid in my layout...
How do I set different column size on first row and full width on second row?
Is this possible?
Thank you so much!!!
This is not possible, the idea of css grid is to have a "grid", that is all the rows follow the same column configuration.
What you can do however is have an element span several column, and here you have several options:
This one stretches from the first column to the first from the end
div:nth-child(3) {
grid-column: 1 / -1;
}
This one spans 2 columns from the first one:
div:nth-child(3) {
grid-column: 1 / span 2;
}
i have the following structure :
root grid
grid1
grid2
grid3
I define the columns : repeat(5 1fr)
the problem is that because the content they have different widths.
Is there a way somehow to pick the largest element width and set it as min-width to the other 2 grids.
Something like this /pseudo code/:
repeat(5 minmax(max(grid1.cells.width,grid2.cells.width,grid3.cells.width)), 1fr))
or in case i know which grid will be widest :
repeat(5 minmax(grid2.cells.width, 1fr))
this is very hacky non automatic solution:
let min_width = window.getComputedStyle(grid2.children[0]).width
grid1.style.gridTemplateColumns = `repeat(${grid1_ncols}, minmax(${min_width}, 1fr))`
a better one ??
I am trying to make a simple sidebar layout with a flat HTML structure, in which the first <aside> element fills in the 1st column completely.
My problem is, that the negative row end value seems to not work for the implicitly created rows for all my elements in the 2nd column.
Expected:
Actual:
Below is a runnable code snippet that illustrates the problem.
article {
display: grid;
grid-template-columns: 200px 1fr;
background: gray;
}
aside {
grid-row: 1/-1;
grid-column: 1/2;
background: pink;
}
section {
grid-column: 2/3;
background: yellow;
}
<article>
<aside>In the left column (top to bottom)</aside>
<section>In the right column</section>
<section>In the right column</section>
<section>In the right column</section>
</article>
You can only use negative integers in an explicit grid.
See the Grid spec here:
7.1. The Explicit
Grid
Numeric indexes in the grid-placement properties count from the edges
of the explicit grid. Positive indexes count from the start side
(starting from 1 for the start-most explicit line), while negative
indexes count from the end side (starting from -1 for the end-most
explicit line).
and here...
8.3. Line-based Placement: the grid-row-start, grid-column-start, grid-row-end, and grid-column-end properties
If a negative integer is given, it instead counts in reverse, starting
from the end edge of the explicit grid.
Making a grid area span an entire column / row, including implicit tracks, when the number of tracks in the grid is unknown, is not possible in CSS Grid Level 1, unless you want to try to hack it.
I tried to develop ui table control with multi select option.
The label of each column is sap.m.Text:
But when i re size the column width, parts from the label text are hide:
It's all because of the "sapUiSizeCozy" class for the multi select option (the checkbox)
When i don't use this "sapUiSizeCozy" class the label text will be OK and wrapped, but, there will no be checkboxex:
I add this css class to the sap.m.Page control
Any help?
I need that the label will wrapped + the checkbox in each row
Thanks!
Edit:
Please see an example in:
Plunker
You can in view.xml file remove the:
class="sapUiSizeCozy"
And re size the Product Name" column to see that the column is wrapping
sapUiSizeCozy sets a fixed height to the table header. The label text is then verticaly centered by sapUiSizeCozy by setting lineheight to the height of the header.
This results in the effect that the label is wrapped but the second row is cut of by the fixed header height.
You can fix that with the following css (see Plunker):
<html:style>
.sapUiSizeCozy .sapUiTable .sapUiTableColCell>* span{
line-height: normal;
vertical-align: middle;
display: inline-block;
}
</html:style>