I am using CSS Grid to display some tags. If a tag is large (ie. it's width is more than 150px), I would like that item to span into more columns as needed. For example, in the image I would like the red tag to span into two columns so that the text remains in one line.
Is it possible to do something like that without adding a specific class to the target element? I am mapping through an array in React to generate each of these divs so it won't be possible to add a class to that element only.
index.js
<div className={styles.container}>
<>
{tags.map(tag => {
return <TagBlock tag={tag} />
})}
</>
</div>
style.css
.container {
margin: 30px auto;
width: 90%;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(150px, auto));
grid-gap: 20px;
}
Don't know a way to implement a gradual column width increase via CSS only. A JS logic will be required to set "how many columns it should take". Then one of the following cases.
explicitly style for the "wide" column:
grid-column: span X;
where X is how many columns should take your element.
Set predefined classes (like at Bootstrap: col-1, col-2), then apply them.
If a column could have any width, then I would recommend you to use a flexbox with wrapping. Kind of:
.container {
margin: 30px auto;
width: 90%;
/*added properties below*/
display: flex;
flex-wrap: wrap;
align-content: flex-start;
}
/*TagBlock base style that grid generated on its own*/
TagBlock {
margin: 25px;
min-height: 120px;
min-width: 120px;
}
Hope, this will help a little.
Related
I have two divs inside a flex box. Div A is on the left, and div B is on the right.
I would like div A to take up 60% of the flex box, and div B to take up 40% of the flex box. As you can imagine, my css will look like this:
.container {
display: flex;
justify-content: start;
flex-direction: column;
}
.div_a {
width: 60%;
}
.div_b {
width: 40%;
}
Also, the browser will look like this:
Now, I would like div B to have a maximum and minimum width, the code will now look like this:
.container {
display: flex;
justify-content: start;
flex-direction: column;
}
.div_a {
width: 60%;
}
.div_b {
width: 40%;
max-width: 768px;
min-width: 480px;
}
Unfortunately, this will lead to this situation large browsers.
When Div B has reached its maximum width, I would like div A to fill up the rest of the space, like this:
Any ideas or fixes would be appreciated, thank you very much in advance.
I should mention that min-width: 60% for Div A produces the same situation, unfortunately.
This is a perfect case where you would turn towards the property flex-grow.
Since you're working with a 60%/40% size, you can use flex-grow:6 and flex-grow:4, or alternatively: flex-grow:3 and flex-grow:2. Or even: flex-grow:1.5 and flex-grow:1 since the property also accepts decimals!
.div_a {
flex-grow:3;
}
.div_b {
flex-grow: 2;
max-width: 768px;
min-width: 480px;
}
flex-grow is a property that will tell the parent (flexbox) to divide the available width into whatever the sum is of the amount of flex-grow specified in its child elements. By limiting the max width of .div_b, you tell flexbox to stop increasing the width after it reached that max, and the remaining width will be reserved for the other elements (.div_a in this case).
Also
I do want to point out that you're using flex-direction:column, but you're trying to create a row based layout. It's a better idea to use flex-flow: row nowrap. Which is a shorthand to declare both flex-direction and flex-wrap together and, with the value row nowrap will tell the parent to force everything on one line in a horizontal layout.
.container {
display: flex;
justify-content: start;
// flex-direction: column;
flex-flow: row nowrap;
}
I am trying to style the selection panel such that the items display in several columns, but the last item of each column seems to become off-center and split, with the overflow starting at the top of the next column. Ideally the scroll would be vertical, but instead it seems to scroll horizontal to cover the overflow. My list has 30+ items and multiple selections are allowed. The goal is to display as many options as possible to the user at once so they don't have to scroll too much.
Full StackBlitz:
https://stackblitz.com/edit/angular-bt3gs6
select-multiple-example.scss
.toppings-panel.mat-select-panel {
column-count: 2;
column-width: 200px;
width: 400px;
max-width: 400px;
}
select-multiple-example.html
<mat-select [formControl]="toppings" panelClass="toppings-panel" multiple>
<mat-option *ngFor="let topping of toppingList" [value]="topping">{{topping}}</mat-option>
</mat-select>
select-multiple-example.ts
export class SelectMultipleExample {
toppings = new FormControl();
toppingList: string[] = ['Pepperoni', 'Sausage', 'Ham', 'Bacon', 'Chicken',
'Mushroom', 'Red onion', 'White onion', 'Tomato', 'Olives',
'Green bell peppers', 'Pineapple', 'Artichoke', 'Spinach',
'Basil', 'Hot pepper flakes',
'Parmesan', 'Shredded cheddar', 'Extra mozzarella'];
}
The problem with the columns that become off-center and split, is the height of the .mat-select-panel.
It has max-height:256px; (setted in Angular Material code). But, since it has a horizontal scrollbar (which has a height of 17px, in Windows - Chrome), the available remaining space will be: 256 - 17 = 239px.
The height of the mat-option is 48px, so 5 options in a column will take 240px.
A quick solution would be to increase the height of the .mat-select-panel to 257px:
Demo: https://stackblitz.com/edit/angular-bt3gs6-wxwkgg
But, the example above will not display correctly on MacOS; which displays scrollbars like an absolute positioned content, and it has more space available:
I've found a cross platform solution by removing columns (which are kind of difficult to implement cross-browser and cross-platform) and taking an
approach with display: flex for the .mat-select-panel element:
Horizontal scrolling:
.toppings-panel.mat-select-panel {
width: 400px;
max-width: 400px;
display: flex;
flex-direction: column;
flex-wrap: wrap;
min-height: 257px; // min-height needed for windows browsers
}
.toppings-panel.mat-select-panel .mat-option {
min-width: 50%; // 50% to have 2 columns visible
}
Demo: https://stackblitz.com/edit/angular-bt3gs6-lwvwav
Vertical scrolling:
If you prefer vertical scrolling, just remove flex-direction: column; from the code above and play with the max-height in order to set the default visible rows:
.toppings-panel.mat-select-panel {
width: 400px;
max-width: 400px;
display: flex;
flex-wrap: wrap;
max-height: 240px; /* 240px - for 5 items / column */
}
.toppings-panel.mat-select-panel .mat-option {
min-width: 50%;
}
Demo: https://stackblitz.com/edit/angular-bt3gs6-iykn4w
I am working on a web application that has a member list. The quantity of member will come dynamically from the server. I want to show each member's info in a grid of four columns.
Is it possible to dynamically place each item from right to left using Css Grid?
You should use direction property:
.container
{
display: grid;
grid-template-columns: 25vw 25vw 25vw 25vw;
grid-template-rows: 100vh; /* Your number of rows */
grid-auto-flow: column;
direction: rtl;
}
I'm trying to aim for a responsive design wherein a long list of links is arranged in columns, the number of columns varying according to the width of the display device screen. As I understand it, I must specify the height of the container to get multiple columns. However, then the columns continue to the right off the screen. I do not know the length of the links. Is there any way to do this through Flexbox? It seems like such an obvious requirement.
The CSS I have so far is:
/* Container */
.links {
display: flex;
flex-direction: column;
flex-wrap: wrap;
width: 100vw !important;
height: 90vh;
}
/* Links in Container */
.links a {
white-space: nowrap;
flex: 1;
margin: 5px 5px 0 20px;
}
Edit: this it NOT a duplicate as commented. The problem not that the container width doesn't grow horizontally. The problem is that it DOES grow horizontally, not vertically.
Have you considered just using CSS Columns?
You wouldn't need to specify any height and then as the screen width changes, the number of columns will adjust based on the width you specify - taking up whatever height it needs, accordingly.
Your CSS could just look like this:
.links {
columns: 5 100px; // # of columns | minimum column width
column-gap: 40px; // space between columns
}
.links > a {
display: block;
padding: 10px 5px;
}
<div class="links">
link1
link2
link3
link4
link5
link6
link7
link8
link9
link10
link11
link12
link13
link14
link15
link16
link17
link18
link19
link20
</div>
Browser support for columns is pretty good.
Hope this helps!
I have a CSS grid layout where I have the top row spanning the entire grid using the grid-column property.
Does anyone know how I can set this row to be 100px high and have all the subsequent rows set to a grid-auto-rows height of 200px?
I know I can input individual values with grid-template-rows for all the specific rows, but there are going to be a lot of divs on the page and don't want to input 100px and then a load of 200px values using this grid-template-rows property.
I'm thinking there must be a way to set individual pixel values on certain rows and then have everything else as grid-auto-rows?
I can't seem to find how to do this in the docs.
Any help would be awesome!
https://codepen.io/emilychews/pen/dZPJGQ
.gridwrapper {
display: grid;
grid-template-columns: repeat(2, 2fr);
grid-auto-rows: 200px;
grid-template-rows: 100px 200px;
grid-gap: 10px;
}
nav {
background: yellow;
}
.gridwrapper div {
padding: 1em;
background: red;
color: white;
box-sizing: border-box;
}
.gridwrapper div:nth-child(odd) {
background: blue;
}
nav {
grid-column: 1 / -1;
}
/*MAKE DIVS 1FR ON MOBILE*/
#media only screen and (max-width: 736px) {
.gridwrapper {
grid-template-columns: 1fr;
}
}
<div class="gridwrapper">
<nav class="grid">1</nav>
<div class="grid">2</div>
<div class="grid">3</div>
<div class="grid">4</div>
<div class="grid">5</div>
<div class="grid">6</div>
</div>
Does anyone know how I can set this row to be 100px high and have all the subsequent rows set to a grid-auto-rows height of 200px?
Yes. Grid can do this cleanly and easily.
First, you don't need to set a height value on the grid item itself. That overrides one of the great benefits of CSS Grid: the ability to control the dimensions of grid items at the container level.
You know that your grid will always have at least one row: the top row. That's your explicit grid.
You don't know how many additional rows there will be. That number is variable and unpredictable. That's your implicit grid.
The grid-template-rows and grid-template-columns properties set track sizes in the explicit grid.
The grid-auto-rows and grid-auto-columns properties set track sizes in the implicit grid.
Therefore, this is probably what you're looking for:
.gridwrapper{
display: grid;
grid-template-rows: 100px; /* top row is 100px in height */
grid-auto-rows: 200px; /* any new rows created are 200px in height */
}
revised codepen
You can use grid-template-rows property.
I guess you are looking for something like this:
https://codepen.io/harora/pen/EbaQxr
Here is a nice reference to the Grid model:
Grid Model Explained