Grouping selected items is a design choice often employed to help users quickly grasp which items are selected and unselected. For instance, checked-off items move up the list in to-do lists, allowing users to focus on the remaining tasks when they revisit the list.
We’ll design a UI that follows a similar grouping pattern. Instead of simply rearranging the list of selected items, we’ll also lay them out horizontally using CSS Grid. This further distinguishes between the selected and unselected items.
We’ll explore two approaches for this. One involves using auto-fill
, which is suitable when the selected items don’t exceed the grid container’s boundaries, ensuring a stable layout. In contrast, CSS Grid’s span
keyword provides another approach that offers greater flexibility.
The HTML is the same for both methods:
<ul>
<li>
<label>
<input type="checkbox" />
<div class=icon>🍱</div>
<div class=text>Bento</div>
</label>
</li>
<li>
<label>
<input type="checkbox" />
<div class=icon>🍡</div>
<div class=text>Dangos</div>
</label>
</li>
<!-- more list items -->
</ul>
The markup consists of an unordered list (<ul>
). However, we don’t necessarily have to use <ul>
and <li>
elements since the layout of the items will be determined by the CSS grid properties. Note that I am using an implicit <label>
around the <input>
elements mostly as a way to avoid needing an extra wrapper around things, but that explicit labels are generally better supported by assistive technologies.
Method 1: Using auto-fill
ul {
width: 250px;
display: grid;
gap: 14px 10px;
grid-template-columns: repeat(auto-fill, 40px);
justify-content: center;
/* etc. */
}
The <ul>
element, which contains the items, has a display:
grid
style rule, turning it into a grid container. It also has gaps of 14px
and 10px
between its grid rows and columns. The grid content is justified (inline alignment) to center
.
The grid-template-columns
property specifies how column tracks will be sized in the grid. Initially, all items will be in a single column. However, when items are selected, they will be moved to the first row, and each selected item will be in its own column. The key part of this declaration is the auto-fill
value.
The auto-fill
value is added where the repeat count goes in the repeat()
function. This ensures the columns repeat, with each column’s track sizing being the given size in repeat()
(40px
in our example), that will fit inside the grid container’s boundaries.
For now, let’s make sure that the list items are positioned in a single column:
li {
width: inherit;
grid-column: 1;
/* Equivalent to:
grid-column-start: 1;
grid-column-end: auto; */
/* etc. */
}
When an item is checked, that is when an <li>
element :has()
a :checked
checkbox, we’re selecting that. And when we do, the <li>
is given a grid-area
that puts it in the first row, and its column will be auto-placed within the grid in the first row as per the value of the grid-template-columns
property of the grid container (<ul>
). This causes the selected items to group at the top of the list and be arranged horizontally:
li {
width: inherit;
grid-column: 1;
/* etc. */
&:has(:checked) {
grid-area: 1;
/* Equivalent to:
grid-row-start: 1;
grid-column-start: auto;
grid-row-end: auto;
grid-column-end: auto; */
width: 40px;
/* etc. */
}
/* etc. */
}
And that gives us our final result! Let’s compare that with the second method I want to show you.
Method 2: Using the span
keyword
We won’t be needing the grid-template-columns
property now. Here’s the new <ul>
style ruleset:
ul {
width: 250px;
display: grid;
gap: 14px 10px;
justify-content: center;
justify-items: center;
/* etc. */
}
The inclusion of justify-items
will help with the alignment of grid items as we’ll see in a moment. Here are the updated styles for the <li>
element:
li {
width: inherit;
grid-column: 1 / span 6;
/* Equivalent to:
grid-column-start: 1;
grid-column-end: span 6; */
/* etc. */
}
As before, each item is placed in the first column, but now they also span
six column tracks (since there are six items). This ensures that when multiple columns appear in the grid, as items are selected, the following unselected items remain in a single column under the selected items — now the unselected items span across multiple column tracks. The justify-items: center
declaration will keep the items aligned to the center.
li {
width: inherit;
grid-column: 1 / span 6;
/* etc. */
&:has(:checked) {
grid-area: 1;
width: 120px;
/* etc. */
}
/* etc. */
}
The width of the selected items has been increased from the previous example, so the layout of the selection UI can be viewed for when the selected items overflow the container.
Selection order
The order of selected and unselected items will remain the same as the source order. If the on-screen order needs to match the user’s selection, dynamically assign an incremental order
value to the items as they are selected.
onload = ()=>{
let i=1;
document.querySelectorAll('input').forEach((input)=>{
input.addEventListener("click", () => {
input.parentElement.parentElement.style.order = input.checked ? i++ : (i--, 0);
});
});
}
Wrapping up
CSS Grid helps make both approaches very flexible without a ton of configuration. By using auto-fill
to place items on either axis (rows or columns), the selected items can be easily grouped within the grid container without disturbing the layout of the unselected items in the same container, for as long as the selected items don’t overflow the container.
If they do overflow the container, using the span
approach helps maintain the layout irrespective of how long the group of selected items gets in a given axis. Some design alternatives for the UI are grouping the selected items at the end of the list, or swapping the horizontal and vertical structure.
Grouping Selection List Items Together With CSS Grid originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
from CSS-Tricks https://ift.tt/WMIKXqA
via IFTTT
No comments:
Post a Comment