<main>
<button id="xray" onclick="toggleXRay(event)">Grid X-Ray Vision!</button>
<h1>Ridiculously responsive lists with CSS Grid</h1>
<p>For those times when you have a long list of short items and you want to be able to lay them out with a bit of density. Click the Grid X-Ray Vision button to get a better idea of what's happening.</p>
<h2>Here be lists!</h2>
<div class="container">
<h3 class="header1">Segment 1</h3>
<ul class="list1 responsive green-checkmarks">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Many items</li>
<li>Coffee</li>
<li>Milk</li>
<li>Tea</li>
<li>Black tea</li>
<li>Green tea</li>
<li>I need more items</li>
<li>Some short</li>
<li>Some long but not too long</li>
<li>Last item</li>
</ul>
<h3 classs="header2">Second segment</h3>
<ul class="list2 responsive green-checkmarks">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Some long but not too long</li>
<li>Many items</li>
<li>Green tea</li>
<li>And that should be it</li>
<li>Some other item</li>
<li>I need more items</li>
<li>Last item</li>
</ul>
</div>
<h2>Things to improve</h2>
<ul class="red-crosses">
<li>I don't like the fact that I'm setting the minimum column width with a fixed length using <span class="code">repeat(auto-fit, minmax(25ch, 1fr))</span>. I'd like to use <span class="code">max-content</span> instead of <span class="code">25ch</span> so that the columns are as wide as they need to be for the text to fit in one line, but I can't seem to make it work 🤷♂️.</li>
</ul>
</main>
<footer>
<p>If you have questions or comments, <a href="https://twitter.com/raulrpearson">tweet</a> them to me!</p>
</footer>
/* Reset! */
* {
margin: 0;
padding: 0;
}
main {
padding: 1em;
font-size: 1.1em;
}
// Target all headings
// https://stackoverflow.com/a/21622588
h1, h2, h3,
h4, h5, h6 {
@extend %headings !optional;
}
%headings {
font-family: sans-serif;
font-weight: normal;
}
main > %headings {
margin: 1em 0 0.5em 0;
}
p {
margin: 0.5em 0;
}
/* The part that you care about */
.container {
display: grid;
grid-template-areas:
"header1 header2"
"list1 list2";
@media (max-width: 700px) {
grid-template-areas:
"header1"
"list1"
"header2"
"list2";
}
}
.header1 { grid-area: header1; }
.header2 { grid-area: header2; }
.list1 { grid-area: list1; }
.list2 { grid-area: list2; }
ul.responsive {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(25ch, 1fr));
//grid-auto-flow: column;
//grid-auto-columns: max-content;
justify-items: start;
align-self: start;
}
/* Set up Grid X-ray vision */
.container,
ul {
grid-gap: 2px;
}
.xray {
background: #0000001f;
}
button#xray {
font-size: 0.7em;
position: sticky;
top: 1em;
display: block;
margin: 0 0 0 auto;
padding: 0.5em;
border: 0;
color: white;
background-color: purple;
&:hover {
filter: brightness(90%);
}
}
/* Make things look a bit better */
ul {
&.green-checkmarks,
&.red-crosses {
list-style: none;
margin-left: 0;
padding-left: 0;
li {
padding-left: 1.1em;
text-indent: -1.1em;
}
}
&.green-checkmarks li:before {
font-family: 'Font Awesome 5 Free';
content: "\f00c";
color: green;
padding-right: 0.3em;
}
&.red-crosses li:before {
font-family: 'Font Awesome 5 Free';
content: "\f00d";
color: red;
padding-right: 0.3em;
}
}
.code {
font-family: monospace;
font-weight: bold;
color: gray;
}
#twitter {
position: absolute;
top: 1em;
left: 1em;
color: #1da1f2;
font-size: 1.2em;
}
footer {
background: purple;
color: white;
padding: 0.5em;
margin-top: 2em;
text-align: center;
font-size: 0.7em;
a {
color: #62BDEE;
text-decoration: none;
font-weight: bold;
}
}
View Compiled
/* Gather up the Grids! (including children and grandchildren) */
let allElements = Array.from(document.querySelector('main').children);
let allGrids = [];
allElements.forEach(
element => {
if (window.getComputedStyle(element).getPropertyValue('display') == 'grid') {
allGrids.push(element);
Array.from(element.children).forEach(
child => {
allGrids.push(child);
Array.from(child.children).forEach(
granchild => {
allGrids.push(granchild);
}
)
}
)
}
}
);
/* Boom, x-ray! */
let xrayActive = false;
function toggleXRay(e) {
xrayActive ?
allGrids.forEach(element => element.classList.remove('xray')) :
allGrids.forEach(element => element.classList.add('xray'));
xrayActive = !xrayActive;
}
This Pen doesn't use any external JavaScript resources.