<div class="layout">
  <div class="container">
    <h2>Flexbox: flex-wrap and flex</h2>
    <ul class="flex">
      <li>1</li>
      <li>2</li>
      <li>3</li>
      <li>4</li>
      <li>5</li>
      <li>6</li>
      <li>7</li>
    </ul>
  </div>

  <div class="container">
    <h2>Grid: auto-fit and minmax()</h2>
    <ul class="grid">
      <li>1</li>
      <li>2</li>
      <li>3</li>
      <li>4</li>
      <li>5</li>
      <li>6</li>
      <li>7</li>
    </ul>
  </div>
</div>

<form>
  <div class="control">
    <label for="ideal-item-size">理想宽度:</label>
    <input type="number" min="100" max="500" step="10" value="400" id="ideal-item-size" name="ideal-item-size" />
    <span>px</span>
  </div>
  <div class="control">
    <label for="gap">列间距:</label>
    <input type="number" min="4" max="36" step="4" value="20" id="gap" name="gap" />
    <span>px</span>
  </div>
  <div class="control">
    <label for="n">列数N:</label>
    <input type="number" min="4" max="7" step="1" value="4" id="n" name="n" />
  </div>
  <div class="control">
    <label for="m">列数M:</label>
    <input type="number" min="2" max="5" step="1" value="2" id="m" name="m" />
  </div>
</form>
@import url("https://fonts.googleapis.com/css2?family=Exo:wght@600&display=swap");

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  width: 100vw;
  min-height: 100vh;
  font-family: "Exo", Arial, sans-serif;
  background-color: #557;
  color: #fff;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--gap);
}

.layout {
  padding: 1rem;
  border: 1px dashed #09f;
}

ul {
  list-style: none outside none;
}

h2 {
  margin-bottom: 1rem;
}

li {
  background-color: #09f;
  font-size: clamp(2rem, 2vw + 2rem, 3rem);
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 6px;
  box-shadow: 0 0 1px 2px rgb(0 0 0 / 0.125);
  text-shadow: 1px 1px 0 rgb(0 0 0 / 0.25);
  min-height: 120px;
}

form {
  width: min(320px, 100%);
  padding: 1rem;
  background-color: rgb(0 0 0 / 0.6);
}

.control {
  display: grid;
  grid-template-columns: 1fr 3.6em 100px;
  gap: 5px;
  align-items: center;
}

.control:not(:last-child) {
  margin-bottom: 1rem;
}

.control label {
  text-align: right;
}

form input[type="number"] {
  width: clamp(3em, 100%, 6em);
  background: rgb(255 255 255 / 0.3);
  outline: none;
  padding: 10px 2px 10px 10px;
  font-size: 13px;
  color: #fff;
  text-shadow: 1px 1px 1px rgb(0 0 0 / 30%);
  border: 1px solid rgba(0, 0, 0, 0.3);
  border-radius: 4px;
  box-shadow: inset 0 -5px 45px rgb(100 100 100 / 20%),
    0 1px 1px rgb(255 255 255 / 20%);
  transition: box-shadow 0.5s ease;
}

form input[type="number"]:focus {
  box-shadow: inset 0 -5px 45px rgb(100 100 100 / 40%),
    0 1px 1px rgb(255 255 255 / 20%);
  border-color: #0c69f3;
}

@media screen and (max-width: 768px) {
  body {
    grid-template-columns: auto;
    grid-template-rows: 1fr auto;
  }

  form {
    width: 100%;
  }
}

.container + .container {
  margin-top: 2rem;
}

:root {
  --ideal-item-size: 400px;
  --n: 4;
  --m: 2;
  --gap: 20px;
  --responsive-item-size: clamp(
    100% / (var(--n) + 1) + 0.1%,
    (var(--ideal-item-size) - 100vw) * 1000,
    100% / (var(--m) + 1) + 0.1%
  );
}

.flex {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap);
}

.flex li {
  flex: var(--responsive-item-size);
}

.grid {
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(
    auto-fit,
    minmax(var(--responsive-item-size), 1fr)
  );
}
const rootElement = document.documentElement;
const inputs = document.querySelectorAll('input[type="number"]');

inputs.forEach((input) => {
  input.addEventListener("input", (etv) => {
    if (etv.target.id === "n") {
      rootElement.style.setProperty(`--n`, etv.target.value);
    } else if (etv.target.id === "m") {
      rootElement.style.setProperty(`--m`, etv.target.value);
    } else {
      rootElement.style.setProperty(
        `--${etv.target.id}`,
        `${etv.target.value}px`
      );
    }
  });
});
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.