At 50% width you don’t account for margins and padding. Setting box-sizing: border-box will take care of padding and borders, but you will have to go below 50% to account for margins.
I don’t see why you have both flex-basis and width set.
No need to state the obvious (i,e. the flex defaults) which save a few lines.
The 4 across needs no widths because flex-basis:0% combined with flex:grow:1 will automatically equalise all box widths on the first line (assuming only 4 elements are present at all times ).
When you go to 2 across then you need a basis to split only 2 on a line but you then need to accommodate the 5px right margin. I used calc in the above example to be exact but a percentage value less than say 48% would do but is a guesstimate.
Yes that’s basically what I usually do and what I meant with that comment above. I was assuming flex grow was set to 1 as in my example
The only problem is that it’s still a guesstimate as you have to work out if the percentage you shorten is actually less than the margin required. You could of course specify a much smaller percentage for extra safety but must be greater than 33.3% otherwise you’d get 3 across.
Using calc you can be exact but cries out for using css variables so that the margin value can be tied to the basis to avoid changing one but not the other.