So I have a bunch of stuff in a grid. The following is an extremely reduced example, but demonstrates the issue. The actual grid items have "natural content" sizes, but here I have given them various specific widths in px. The background colors show the (simulated) content width of the grid items. In row 2, the items are large and span 3 grid columns. In row 1, the items are shorter, so the grid algorithm adds gaps between items.
Remembering that the sizes are actually based on content, and are unknown to the HTML & CSS, I would like to control where the grid algorithm places the gaps. As an example, let's say that I would like the gaps for items 1-3, to all be between items 2 and 3, with item 1 left aligned (as it is) with item 11, item 2 juxtaposed with item 1, then a gap, and then item 3 to be right-aligned. This can be achieved by uncommenting the first grid-template-columns rule.
Now let's say that I would INSTEAD like the gaps for items 4-6 to be between items 4 and 5. This can be achieved by uncommenting the second grid-template-columns rule.
Now here is the question: is there a different technique that can be used to achieve control over both of these gaps? Uncommenting the third grid-template-columns rule demonstrates that this technique can only be used in one spot per grid, because the gap sizes are different for the two cases, and it introduces gaps in row 2, which is not wanted.
.gr
{
display:grid;
width:max-content;
grid-auto-columns:max-content;
/* grid-template-columns:auto 1fr repeat( 8, auto ); */
/* grid-template-columns:repeat( 4, auto ) 1fr repeat( 5, auto ); */
/* grid-template-columns:auto 1fr repeat( 2, auto ) 1fr repeat( 5, auto ); */
/* grid-template-columns:auto 1fr repeat( 2, auto ) ??? repeat( 5, auto ); */
}
.wide
{
grid-column:span 3;
grid-row: 2;
}
.w1
{
width:125px;
background-color:yellow;
}
.w2
{
width:110px;
background-color:palegreen;
}
.w3
{
width:140px;
background-color:yellow;
}
.w4
{
width:75px;
background-color:palegreen;
}
.a
{
background-color:red;
grid-row: 1;
width:20px;
}
.b
{
background-color:green;
grid-row: 1;
width:30px;
}
.c
{
background-color:purple;
grid-row: 1;
width:40px;
}
.d
{
background-color:lightblue;
grid-column:span 3;
grid-row: 1;
width:100px;
}
<h1>grid gaps</h1>
<div class=gr>
<div class=a>1</div>
<div class=b>2</div>
<div class=c>3</div>
<div class=c>4</div>
<div class=a>5</div>
<div class=b>6</div>
<div class=d>7</div>
<div class=b>8</div>
<div class=c>9</div>
<div class=a>10</div>
<div class="wide w1">11</div>
<div class="wide w2">12</div>
<div class="wide w3">13</div>
<div class="wide w4">14</div>
</div>
Related
I have a slider that ranges from 1 and up to 3. The slider's on change event sets the value of a CSS variable (e.g. :root { --colNum: 1 } ) so I am able to dynamically change the number of grid columns.
What I am trying to achieve is (let's say I have six images in total):
When I have one column set, I would like to display only the first image, full size and hide the five remaining images.
When I have two columns set, I would like to display the first four images, two in each row and hide the two remaining images.
When I have three columns set, I would like to display all the six images, three per row.
Similar to the following images:
1 column and 1 image (1 row)
2 columns and 4 images (2 rows)
3 columns and 6 images (2 rows)
I have created a sandbox, tried different examples but none of them fit my needs so I have left it in an "initial state".
I am not sure if I am overthinking that but I am open to hear any suggestions or even other approaches in how I could achieve that result.
Thanks in advance.
I have finally achieved what I wanted. Maybe it can help someone else facing similar case as mine.
The solution is going to be in the same sandbox and I will be improving that to completely fit my needs.
Solution
In short, as I previously mentioned I have the CSS var (--colNum) changing its value dynamically based in the slider value.
I have filtered the items from the images array to conditionally render or not the images based in the colNum and image index values.
If I have a condition which renders the images I pass down a style props containing the height and width of the images and in cases it should not render I just return null.
Probably not the best approach but still.
const imagesByColumn = images.map((image, index) => {
// One Image One Column
if (colNum === '1') {
if (index === 0) {
const style = { width: '300px', height: '200px' };
return <Image key={index} url={image.url} style={style} />;
} else {
return null;
}
}
// Two Columns 4 Images
if (colNum === '2') {
if (index >= 0 && index < 4) {
const style = { width: '170px', height: '120px' };
return <Image key={index} url={image.url} style={style} />;
} else {
return null;
}
}
// 3 Columns 6 Images
if (colNum === '3') {
const style = { width: '150px', height: '100px' };
return <Image key={index} url={image.url} style={style} />;
}
return null;
});
I have a grid container of dynamic width, with an unknown number of children. These children will have a varying and unknown amount of text within them.
I know it's possible to make the number of columns dynamic:
grid-template-columns: repeat(auto-fill, minmax(100px, 150px));
However the CSS above sets the minimum width of each column to be 100px and the maximum to be 150px. Is it possible to have no maximum and instead let this be defined by the child elements text content?
I tried this but it actually makes the columns smaller:
grid-template-columns: repeat(auto-fill, minmax(100px, auto));
Okay, I have tried grid and it isn't working as expected, you can use flex instead,
.wrapper{
display: flex;
flex-wrap: wrap;
}
/*
you can add some max-width to the children elements
*/
.wrapper > div {
max-width: 50%; /*Any other with will work*/
width: 100px; /* the min width of the div */
}
I want to change how the row expands for different breakpoints like below. Basically allow expanded below medium and unexpand above large breakpoint.
<div class="small-expanded large-unexpanded row">
<div class="small-12 columns"></div>
</div>
I know this class is not available but how can I achieve this.
I'm not sure why you'd want to do this, the row automatically expand to the available width, until it reaches the maximum width, and then stays at that width (default max width is 1200px, can be changed on customizer or SASS settings), however we can create those class you're mention.
Code: (assuming you're using the standard breakpoints)
/* small and up */
.row.small-expanded { max-width: none }
.row.small-unexpanded { max-width: 75em }
#media screen and (min-width: 40em) { /* medium and up */
.row.medium-expanded { max-width: none }
.row.medium-unexpanded { max-width: 75em }
}
#media screen and (min-width: 40em) { /* large and up */
.row.large-expanded { max-width: none }
.row.large-unexpanded { max-width: 75em }
}
This code is mobile-first, so, if you have <div class="small-expanded large-unexpanded">, medium breakpoint will take the same styles from the lower breakpoint (small).
Of course, if you've modified framework metrics (breakpoints, max width), you should thange the above code as well.
I created a QListWidget using setViewMode(QListView::ListMode) and setFlow(QListView::TopToBottom) to get this:
The large space between the icon and the text looks odd so I tried to remove it with:
list->setStyleSheet("QListView::icon { padding-right: 0px; }");
and also:
list->setStyleSheet("QListView::icon { padding: 0px; }");
but neither removes the space. Is there any way to remove the space between the icon and the text?
Also, you'll see from the above screenshot that QListWidget uses variable column widths, but I wanted all the columns to have the same width. I tried this solution:
int width = 0;
int numItems = list->count();
QFontMetrics metrics(list->font());
for (int i = 0 ; i < numItems ; ++i)
{
if (metrics.boundingRect(list->item(i)->text()).width() > width)
width = metrics.boundingRect(list->item(i)->text()).width();
}
list->setGridSize(QSize(width+30, 16));
However, it doesn't seem to work consistently and I had to use +30 to account for the icon area, which isn't a very good solution, particularly if the size of the icon changes.
Is there a better way to get all the columns the same width?
I can move the "indicator" anywhere I want, but the "Button" and "DiagValue" I ONLY seem to be able move to different rows... I need to move to different columns or different "x".
Row{
spacing: table.rowSpacing
Button {
width: 60
//x: 100 //this does NOTHING!
//y: 159
text: tr_NOOP("Help")
onClicked: {
app.dialogs.message.title = trans("Water Status")
app.dialogs.message.body = trans("Rate is not met.")
app.dialogs.message.show();
}
}
Indicator {
x: -50
//y: 159
ok: false
}
DiagValue {
MeasuredValue {
id: lowFlowValueText
rawValueUnit: "gpm"
unit: "gpm"
precision: 1
}
label: trans("Water Flow Setting")
value: lowFlowValueText.text
}
}
I think if you set proper spacing in Row and align it horizontally, it should look like what you need.
Row {
spacing: table.rowSpacing
anchors.horizontalCenter: parent.horizontalCenter
...
}
And you don't need to supply x value when your elements are inside Row, Row element will decide x value based on spacing and width of individual child.
A Row will define the horizontal location and the horizontal extent (size) of the elements that it contains. It doesn't make sense to manually try to override either x or width for elements in a row, in fact it will generate warnings.
You can, of course, override the vertical position within a Row.
Your elements must be supplying sensible default sizes and must react sensibly to being resized, so without seeing how you define the components (Button, Indicator, DiagValue), it'd be impossible to say exactly where the problem is. For stock controls, it works fine.