There's a lot going on in this layout.
But, essentially, the main problem is a lack of extra height in the container.
Here's what's happening:
Explicit and Implicit Rows
This is what you have:
.container {
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-gap: 10px;
background: black;
}
.item {
display: grid;
border-radius: 2px;
border: 1px solid red;
background-color: var(--yellow);
}
.item3 {
grid-column: 1 / -1;
grid-row: span 3;
}
The .item rule is having no impact on the problem, so let's just leave the borders for illustration purposes.
.container {
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-gap: 10px;
background: black;
}
.item3 {
grid-column: 1 / -1;
grid-row: span 3;
}
.item {
border: 1px solid red;
}
Because you haven't defined grid-template-rows or grid-template-areas, there are no explicit rows. All rows are implicit (created as needed).
The size of implicit rows is governed by grid-auto-rows, whose default value is auto (the size of the content).
So the height of each row is currently defined by the size of the text – the numbers – in your HTML.
The numbers are invisible because the background and text are both black. To better understand the source of the row height, let's change the text color to white.
.container {
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-gap: 10px;
background: black;
color: white; /* new */
}
Here's the full code so far:
.container {
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-gap: 10px;
background: black;
color: white;
}
.item3 {
grid-column: 1 / -1;
grid-row: span 3;
}
.item {
border: 1px solid red;
}
<div class="container">
<div class="item item3">3</div>
<div class="item item4">4</div>
<div class="item item5">5</div>
<div class="item item6">6</div>
<div class="item item7">7</div>
<div class="item item8">8</div>
<div class="item item9">9</div>
<div class="item item10">10</div>
</div>
As stated above, the default height of implicit rows is auto. This means that if grid-auto-rows isn't specified, and there is no content in the grid items, the rows would collapse:
.container {
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-gap: 10px;
background: black;
color: white;
}
.item3 {
grid-column: 1 / -1;
grid-row: span 3;
}
.item {
border: 1px solid red;
}
<div class="container">
<div class="item item3"></div>
<div class="item item4"></div>
<div class="item item5"></div>
<div class="item item6"></div>
<div class="item item7"></div>
<div class="item item8"></div>
<div class="item item9"></div>
<div class="item item10"></div>
</div>
The remaining height in the container comes from the border thickness and the 10px grid gaps. Remove those for a complete collapse (the grid disappears).
.container {
display: grid;
grid-template-columns: repeat(5, 1fr);
/* grid-gap: 10px; */
background: black;
color: white;
}
.item3 {
grid-column: 1 / -1;
grid-row: span 3;
}
.item {
/* border: 1px solid red; */
}
<div class="container">
<div class="item item3"></div>
<div class="item item4"></div>
<div class="item item5"></div>
<div class="item item6"></div>
<div class="item item7"></div>
<div class="item item8"></div>
<div class="item item9"></div>
<div class="item item10"></div>
</div>
The Item 3 Problem
.item3 {
grid-column: 1 / -1;
grid-row: span 3;
}
When you command item3 to span across three rows, it doesn't span across the three existing rows because those tracks are occupied already. However, if you remove the grid-column command, then span 3 works.
.container {
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-gap: 10px;
background: black;
color: white;
}
.item3 {
/* grid-column: 1 / -1; */
grid-row: span 3;
}
.item {
border: 1px solid red;
}
<div class="container">
<div class="item item3">3</div>
<div class="item item4">4</div>
<div class="item item5">5</div>
<div class="item item6">6</div>
<div class="item item7">7</div>
<div class="item item8">8</div>
<div class="item item9">9</div>
<div class="item item10">10</div>
</div>
Let's go back to my first line for a minute: "When you command item3 to span across three rows, it doesn't span across the other two rows because those tracks are occupied already."
That's true. But it's also true that two new rows are created. The grid simply subdivides the first row to fit three.
Here's how it looks using Firefox's Grid Inspector:

Notice how the first row has been divided into three, and the grid now has a total of five rows (because span 3 = existing row + 2).
Let's make it grid-row: span 10 for a better look:

The height of the subdivided first row is coming entirely from the grid-gap, which is adding 10px between each new row.
By the way, that's the explanation for this part of your question:
If I increase the row span value to 4, it works. However the spanning is only 2 rows instead of 4.
You're actually just seeing the effect of 10px row gaps stacking.
If you remove the grid gap, the span will still generate subdivided rows, but these new rows will not change the height of the first row.
Here's the same layout with span 10 again and no grid-gap:

Solutions
Here are three ways to solve the problem.
1. Give the container some height.
If you provide extra height to the container – meaning more height than needed by the content – the grid-row: span 3 will have some space to work.
.container {
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-gap: 10px;
background: black;
color: white;
height: 250px; /* new */
}
.item3 {
grid-column: 1 / -1;
grid-row: span 3;
}
.item {
border: 1px solid red;
}
<div class="container">
<div class="item item3">3</div>
<div class="item item4">4</div>
<div class="item item5">5</div>
<div class="item item6">6</div>
<div class="item item7">7</div>
<div class="item item8">8</div>
<div class="item item9">9</div>
<div class="item item10">10</div>
</div>
2. Define grid-auto-rows.
If you set a height to grid-auto-rows, which controls the height of implicit rows, then grid-row: span 3 will also work.
.container {
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-auto-rows: 50px; /* new */
grid-gap: 10px;
background: black;
color: white;
}
.item3 {
grid-column: 1 / -1;
grid-row: span 3;
}
.item {
border: 1px solid red;
}
<div class="container">
<div class="item item3">3</div>
<div class="item item4">4</div>
<div class="item item5">5</div>
<div class="item item6">6</div>
<div class="item item7">7</div>
<div class="item item8">8</div>
<div class="item item9">9</div>
<div class="item item10">10</div>
</div>
3. Define grid-template-rows.
If you know how many rows you want in the container, set number and height to grid-template-rows, which controls the height of explicit rows.
.container {
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-template-rows: repeat(5, 50px); /* new */
grid-gap: 10px;
background: black;
color: white;
}
.item3 {
grid-column: 1 / -1;
grid-row: span 3;
}
.item {
border: 1px solid red;
}
<div class="container">
<div class="item item3">3</div>
<div class="item item4">4</div>
<div class="item item5">5</div>
<div class="item item6">6</div>
<div class="item item7">7</div>
<div class="item item8">8</div>
<div class="item item9">9</div>
<div class="item item10">10</div>
</div>