<header class="header">
<form class="settings">
<fieldset class="col-left">
<label for="adjustedColumnWidth" class="grid-style">
<input type="radio" checked name="grid-style" value="adjusted-column-width" id="adjustedColumnWidth" class="grid-style"></input>
Adjusted columns width
</label>
<label for="fixedColumnWidth" class="grid-style">
<input type="radio" name="grid-style" value="fixed-column-width" id="fixedColumnWidth" class="grid-style"></input>
Fixed columns width
</label>
</fieldset>
<fieldset class="col-right">
<div class="input-range-wrapper">
<label for="maxCols">
Maximum columns number
</label>
<div class="input-wrapper">
<input type="range" id="maxCols" class="cols-number max-cols" min="1" max="10"></input>
<output class="output"></output>
</div>
</div>
<div class="input-range-wrapper">
<label for="minCols">
Minimum columns number
</label>
<div class="input-wrapper">
<input type="range" id="minCols" class="cols-number min-cols" min="1" max="10"></input>
<output class="output"></output>
</div>
</div>
<div class="input-range-wrapper">
<label for="colsMinWidth">
Columns min width
</label>
<div class="input-wrapper">
<input type="range" id="colsMinWidth" class="cols-min-width" min="0" max="200"></input>
<output class="output"></output>
</div>
</div>
</fieldset>
</form>
<section class="info">
<p class="text">You can resize the with of the container from the bottom right corner</p>
<button id="toggleSettings" class="toggle-settings hide-settings"></button>
</section>
</header>
<main class="content">
<section class="resize">
<h2>justify-content: center</h2>
<div class="parent center parent--adjusted-width">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
<h2>justify-content: space-between</h2>
<div class="parent between parent--adjusted-width">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
<h2>justify-content: space-evenly</h2>
<div class="parent evenly parent--adjusted-width">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
<h2>justify-content: space-around</h2>
<div class="parent around parent--adjusted-width">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</section>
</main>
/* The magic */
/* Mixins for defining a grid with min and max columns */
/* Adjusted columns width */
@mixin grid-cols-adjusted($min-cols, $max-cols, $cols-min-width, $row-gap: 0px, $col-gap: 0px) {
--min-cols: #{$min-cols};
--max-cols: #{$max-cols};
--cols-min-width: #{$cols-min-width};
--row-gap: #{$row-gap};
--col-gap: #{$col-gap};
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min((100%/var(--min-cols) - var(--col-gap)*(var(--min-cols) - 1)/var(--min-cols)), max(var(--cols-min-width), (100%/var(--max-cols) - var(--col-gap)*(var(--max-cols) - 1)/var(--max-cols)))), 1fr));
gap: var(--row-gap) var(--col-gap);
}
/* Fixed columns width */
@mixin grid-cols-fixed($min-cols, $max-cols, $cols-min-width, $row-gap: 0px, $col-gap: 0px) {
--min-cols: #{$min-cols};
--max-cols: #{$max-cols};
--cols-min-width: #{$cols-min-width};
--row-gap: #{$row-gap};
--col-gap: #{$col-gap};
display: grid;
grid-template-columns: repeat(auto-fit, minmax(0, min((100%/var(--min-cols) - var(--col-gap)*(var(--min-cols) - 1)/var(--min-cols)), max(var(--cols-min-width), (100%/var(--max-cols) - var(--col-gap)*(var(--max-cols) - 1)/var(--max-cols))))));
gap: var(--row-gap) var(--col-gap);
}
.parent {
/* Set styles to see the parent */
padding: 1rem 0;
border: 3px solid dodgerblue;
border-radius: 5px;
background: wheat;
/* Grid systems */
$min-cols: 3;
$max-cols: 7;
$cols-min-width: 7.5rem;
$row-gap: 1.5rem;
$col-gap: 1rem;
&--adjusted-width {
@include grid-cols-adjusted($min-cols, $max-cols, $cols-min-width, $row-gap, $col-gap);
}
&--fixed-width {
@include grid-cols-fixed($min-cols, $max-cols, $cols-min-width, $row-gap, $col-gap);
}
&.center {
justify-content: center;
}
&.between {
justify-content: space-between;
}
&.evenly{
justify-content: space-evenly;
}
&.around {
justify-content: space-around;
}
}
.child {
min-height: 3.125rem;
padding: .3125rem 0;
border: 2px solid brown;
border-radius: 5px;
}
/* Styles not related to the goal */
html {
box-sizing: border-box;
height: 100%;
@media (max-height: 22.5rem) {
font-size: 55%;
}
}
*,
*:before, *:after {
box-sizing: inherit;
}
html,
body {
height: 100%;
}
body {
margin: 0;
display: flex;
flex-direction: column;
}
header,
main {
text-align: center;
}
h2 {
margin-bottom: .2rem
}
fieldset,
input {
margin: 0;
padding: 0;
}
.header {
.settings {
padding: .5rem;
font-weight: bold;
background: darksalmon;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
column-gap: 2rem;
row-gap: 1rem;
&.is-hidden {
display: none;
}
.col-left,
.col-right {
display: flex;
flex-direction: column;
gap: .5rem;
border: none;
text-align: left;
}
.col-left {
label {
display: flex;
align-items: center;
gap: .5rem;
}
}
.input-range-wrapper {
display: flex;
flex-direction: column;
gap: .25rem;
.input-wrapper {
display: flex;
align-items: center;
gap: .5rem;
}
}
.cols-min-width + .output {
min-width: 6ch;
}
}
.info {
display: flex;
justify-content: center;
align-items: center;
color: white;
margin: 0;
padding: .5rem;
background: #777;
.text {
flex: 1 0 10rem;
font-weight: bold;
margin: 0;
padding: 0 1rem;
}
.toggle-settings {
display: flex;
align-items: center;
gap: .5rem;
font-size: inherit;
color: white;
background: none;
border: none;
border-left: 2px solid white;
cursor: pointer;
&::before {
content: "▼";
display: inline-block;
transition: transform .5s ease .3s;
}
&::after {
content: "Show settings";
font-size: .9em;
}
&.hide-settings {
&::before {
transform: rotate(180deg);
}
&::after {
content: "Hide settings"
}
}
}
@media (max-width: 22.5rem) {
flex-direction: column;
gap: .5rem;
.text {
flex: 1;
}
.toggle-settings {
padding-top: .4rem;
border-left: none;
border-top: 2px solid white;
}
}
}
}
.content {
flex: 1;
width: 75%;
max-width: 100%;
margin: auto;
padding: 1rem;
overflow: auto;
resize: horizontal;
background-image: linear-gradient(white, lightgray);
}
View Compiled
const parentElements = document.querySelectorAll(".parent");
const gridStyleInput = document.querySelectorAll(".grid-style");
let gridStyle;
gridStyleInput.forEach(input => {
input.addEventListener("input", () => {
if (input.checked) {
gridStyle = input.value;
}
if (gridStyle === "adjusted-column-width") {
parentElements.forEach(parent => {
parent.classList.remove("parent--fixed-width");
parent.classList.add("parent--adjusted-width");
})
}
if (gridStyle === "fixed-column-width") {
parentElements.forEach(parent => {
parent.classList.remove("parent--adjusted-width");
parent.classList.add("parent--fixed-width");
})
}
});
});
const maxColsInput = document.getElementById("maxCols");
const maxColsOutput = document.querySelector("#maxCols + .output");
maxColsInput.value = +getComputedStyle(parentElements[0]).getPropertyValue("--max-cols");
maxColsInput.addEventListener("input", () => {
setMaxCols();
});
const minColsInput = document.getElementById("minCols");
const minColsOutput = document.querySelector("#minCols + .output");
minColsInput.value = +getComputedStyle(parentElements[0]).getPropertyValue("--min-cols");
minColsInput.addEventListener("input", () => {
setMinCols();
});
const colsMinWidthInput = document.getElementById("colsMinWidth");
const colsMinWidthOutput = document.querySelector("#colsMinWidth + .output");
colsMinWidthInput.value = getColsMinWidthValue();
function getColsMinWidthValue() {
let value;
const colsMinWidthValue = getComputedStyle(parentElements[0]).getPropertyValue("--cols-min-width");
const colsMinWidthLowerCase = colsMinWidthValue.toLowerCase();
if (colsMinWidthLowerCase.includes("rem")) {
const colsMinWidthNumeric = +colsMinWidthLowerCase.replace("rem", "");
value = colsMinWidthNumeric * parseFloat(getComputedStyle(document.documentElement).fontSize);
} else if (colsMinWidthLowerCase.includes("%")) {
const colsMinWidthNumeric = +colsMinWidthLowerCase.replace("%", "");
const parentWidth = document.querySelector(".parent").offsetWidth;
value = colsMinWidthNumeric * parentWidth / 100;
} else if (colsMinWidthLowerCase.includes("px")) {
const colsMinWidthNumeric = +colsMinWidthLowerCase.replace("rem", "");
value = colsMinWidthNumeric;
}
if (!value) {
alert("The 3rd parameter for the mixins (min-cols-width) should be set in 'rem', '%' or 'px' units");
return 100;
}
if (value < 0 || value > 200) {
alert("The 3rd parameter for the mixins (min-cols-width) must be between 0 and 200 pixels");
return 100;
}
return value;
}
colsMinWidthInput.addEventListener("input", () => {
setColsMinWidth();
});
function setMaxCols() {
parentElements.forEach(parent => {
parent.style.setProperty('--max-cols', maxColsInput.value);
maxColsOutput.innerText = maxColsInput.value;
});
if (+maxColsInput.value < +minColsInput.value) {
minColsInput.value = maxColsInput.value;
setMinCols();
}
}
setMaxCols();
function setMinCols() {
parentElements.forEach(parent => {
parent.style.setProperty('--min-cols', minColsInput.value);
minColsOutput.innerText = minColsInput.value;
});
if (+minColsInput.value > +maxColsInput.value) {
maxColsInput.value = minColsInput.value;
setMaxCols();
}
}
setMinCols();
function setColsMinWidth() {
parentElements.forEach(parent => {
parent.style.setProperty('--cols-min-width', colsMinWidthInput.value+"px");
colsMinWidthOutput.innerText = colsMinWidthInput.value+"px";
});
}
setColsMinWidth();
const settings = document.querySelector(".settings");
const toggleSettingsButton = document.getElementById("toggleSettings");
toggleSettingsButton.addEventListener("click", () => {
settings.classList.toggle("is-hidden");
toggleSettingsButton.classList.toggle("hide-settings");
})
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.