Interesting challenge – also because you omitted important details
For this example, let’s assume that you have empty lines before and after your images and not embedded the two images in a paragraph of text.
Like that
…last line of previous paragraph

First line of next paragraph
In that case, the generated HTML looks like this
<p>
<img>
<img>
</p>
In former times, you’d probably have used a float
on the second image. Not in 2024, though – we have display: grid
now. So
p:has(img:nth-child(2)) {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 0.5rem;
}
gets you started: Every p
element containing two img
elements (p:has(img:nth-child(2))
) gets a display: grid
with two equally wide columns and a gap between them of 0.5rem.
There’s a very helpful blog post on child-counting:
Note the 1fr
dimension for the grid-template-columns
here: That distributes the free space evenly, i.e. withouth the grid-gap
. If you use 50%
instead of 1fr
, the whole grid will be 0.5rem
wider than the rest of the document.
Now it’s getting more interesting. If you use 
in your MD document, your image width will be 50% of – the parent’s width. And you can’t do anything about it, because in the generated HTML you have <img ... style="width:50%">
– embedded styles override everything in a CSS.
The parent of your img
is now a grid cell (roughly) 50% of the total document width. Which will make your images only a quarter as wide as the document. Not what you want, I presume.
Therefore, I’d take another approach.
- Either, you do not set the
width
of your two images at all in your MD and rely on the CSS to handle paragraphs with two images correctly.
- or, you append a pseudo query string like

to your img
URL and use a more specific selector in your CSS, like
p:has(img[src$="width=half"]:nth-child(2))
Personally, I’d go for the first approach: less typing. And if you apply the same approach to three or four images by adding rules like
p:has(img:nth-child(3)) {
display: grid
grid-template-columns: repeat(3, 1fr);
grid-gap: 0.2rem
}
etc, you can simply determine the outcome by how many images you put in a single paragraph (that is the conditio sine qua non: all images must be in the same line in the MD with an empty line before and after them).
Just take care of the ordering in the CSS: the rules must come in increasing number of children – first 2, then 3 and 4.
Edit
Well, I finished too early, and CSS is way cooler than one tends to think. There’s no need to fiddle around with the number of columns at all:
p:has(img:nth-child(2)) {
grid-auto-columns: 1fr;
grid-auto-flow: column;
grid-gap: 0.2rem;
}
does everything automagically if it sees at least two images in a paragraph. A single rule to rule them all.