CSS: Flexbox Grid com pseudo-seletores ::after e :nth-child

Perceba a importância do estilo .grid-container::after. Ele dispensa a gambiarra de inserir colunas vazias na última linha:

.grid-container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-around;
}

/* Preenche a última linha com espaço vazio */
.grid-container::after {
  content: "";
  flex: auto;
}

.grid-item-3cols {
  width: 33.33%;
}

.grid-item-4cols {
  width: 25%;
}
<ul class="grid-container">
  <li class="grid-item-3cols">Delphi</li>
  <li class="grid-item-3cols">Java</li>
  <li class="grid-item-3cols">PHP</li>
  <li class="grid-item-3cols">Ruby on Rails</li>
</ul>

3 colunas

4 colunas

3 colunas com margem

A classe .grid-container não tem alteração em relação aos exemplos sem margem. A declaração de uma margem de 1% em .grid-item-3cols.margin nos faz redeclarar a largura de cada item em 32.66%:

.grid-item-3cols.margin {
  margin-left: 1%;
  width: 32.66%;
}

.grid-item-3cols.margin:nth-child(3n+1) {
  margin-left: 0;
}
<ul class="grid-container">
  <li class="grid-item-3cols margin">Delphi</li>
  <li class="grid-item-3cols margin">Java</li>
  <li class="grid-item-3cols margin">PHP</li>
  <li class="grid-item-3cols margin">Ruby on Rails</li>
</ul>