0

img {
  height: 50px;
}
<div>
    <div>
      <img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg"/>
      <img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg"/>
      <img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg"/>
    </div>
    <div>
      <img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg"/>
      <img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg"/>
      <img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg"/>
    </div>
</div>

As you can see I managed to arrange the images in two rows however, this required putting them into two two divs. Now the items are dynamically generated and their number is not known upfront. Clearly it's not difficult to write JS that will arrange the items correctly into these two divs however, I'm interested if I can avoid this nonetheless?

Namely, I'm interested if I can write CSS that will arrange all items into evenly-sized rows (that is, eg 4 items in one row nad 4 in the other, not 6 in one row and 2 in the other) without the use of the intermediate divs? So that all imgs will be direct children of the outermost div only and once their number changes (some are added, some are removed) they will rearrange themselves properly without any extra JS code to rearrange them into divs or to change class or inline style of, say, the n/2th img?

EDIT: Just like in my snippet I want the images to occupy only as much horizontal space as necessary and NOT to stretch to the full width of the enclosing container. This is actually required.

  • 1
    can you wrap each img in a `div` ? If you can it will be easier – Viira Nov 02 '18 at 13:24
  • @Viira why not? –  Nov 02 '18 at 13:30
  • I've updated my answer – Viira Nov 02 '18 at 13:41
  • @Pete hmm OK but isnt br Considered Harmful™? This is at least what I seem to recall –  Nov 02 '18 at 13:44
  • 1
    You can use Flexbox + a pseudo as a delimiter: https://jsfiddle.net/8u6sjo3t/ ... and then reposition the pseudo (or both pseudo for 3 rows) with e.g. media query's – Asons Nov 02 '18 at 13:46
  • @Pete Enforcing appearance with HTML. No semantic meaning of the tag. Appearance and item arrangement are CSS's thing, doing this in HTML is a Bad Thing™, so font tags, table tags for non-tabular data, the center tag, br, etc are all out. (Br might be OK for poetry when line breaks do have semantic meaning, but that's it). That's at least what was hammered to my mind a few years ago. –  Nov 02 '18 at 13:47
  • And if you don't want to use a pseudo, add an empty element and use that as a delimiter: https://jsfiddle.net/8u6sjo3t/1/ ... With these options you have full control on how to order the items. – Asons Nov 02 '18 at 13:51
  • @LGSon A nice fiddle, thank you. The problem of it (and all 2 answers) is that if the number of imgs changes some custom JS will have to modify inline CSS so that the break is at the correct place... But I'll guess its unavoidable? –  Nov 02 '18 at 14:09
  • No, you can actually use CSS to detect the amount of children as well: https://stackoverflow.com/questions/8720931/can-css-detect-the-number-of-children-an-element-has – Asons Nov 02 '18 at 14:41
  • And here is 3 markup samples showing "how-to" using your requirement: https://jsfiddle.net/8u6sjo3t/2/ – Asons Nov 02 '18 at 16:53
  • And this sample show the same but with uneven items: https://jsfiddle.net/8u6sjo3t/3/ – Asons Nov 02 '18 at 16:55

3 Answers3

0

You could use a pseudo-element to create a break:

.container>span:nth-child(3n):after {
  content: "\A";
  display: block;
}

img {
  height: 50px;
}
<div class="container">
  <span><img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg" /></span>
  <span><img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg" /></span>
  <span><img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg" /></span>
  <span><img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg" /></span>
  <span><img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg" /></span>
  <span><img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg" /></span>
  <span><img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg" /></span>
  <span><img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg" /></span>
  <span><img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg" /></span>
</div>

If you want 4 on a line, you would use 4n

Pete
  • 57,112
  • 28
  • 117
  • 166
  • Yes but now the images stretch to the full width of the enclosing container. I wanted to avoid that. I wanted them to occupy only as much horizontal space as necessary. Like I showed in my snippet. Perhaps I didn't emphasise this enough in my Q, I'm sorry for that. –  Nov 02 '18 at 13:41
  • With that you might end up with issues if to style the `span` ... feel free to use my fiddle sample I posted in my comments at the question ... after all, they were a small extension of your initial code sample :) – Asons Nov 02 '18 at 13:57
  • @LGSon unfortunately your fiddle would only work if there are 2 rows – Pete Nov 02 '18 at 13:58
  • No, it works for 3 using both pseudo ... still, OP asks for 2 ... and my second sample use an empty span, were one can add as many as needed. – Asons Nov 02 '18 at 13:59
  • A nice answer, thank you. The problem of it is that if the number of imgs changes some custom JS will have to modify inline CSS so that the break is at the correct place... But I'll guess its unavoidable? –  Nov 02 '18 at 14:10
0

Using CSS grid you could:

div{
  display: grid;
  grid-template-columns: repeat(3, 50px);
}
img {
  width: 100%; /* as the column width */
}
<div>
    <img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg"/>
    <img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg"/>
    <img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg"/>
    <img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg"/>
    <img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg"/>
    <img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg"/>
</div>
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
  • A nice answer, thank you. The added benefit is that if one of the imgs is larger it won't break the layout. I think I'd like `inline-grid` more though, tho its a minor modification. The problem of it is that if the number of imgs changes some custom JS will have to modify inline CSS so that the break is at the correct place... But I'll guess its unavoidable? –  Nov 02 '18 at 14:11
  • "The added benefit is that if one of the imgs is larger it won't break the layout." Ugh, only if `min-content` is used instead of `50px` –  Nov 02 '18 at 14:14
  • @gaazkam you can always use `grid-template-columns: repeat(3, auto);` - so `auto` instead of the hardcoded `50px` – Roko C. Buljan Nov 02 '18 at 14:21
0

The solution that seems closest to what I need: (It's a slightly modified version of Roko C. Buljan's solution, so much of the credit goes to him ☺ )

div{
  display: inline-grid;
  grid-template-columns: repeat(3, max-content); 
}
img {
  width: 50px;
}
img:nth-of-type(2) {
  width: 100px;
}
<div>
    <img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg"/>
    <img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg"/>
    <img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg"/>
    <img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg"/>
    <img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg"/>
    <img src="https://upload.wikimedia.org/wikipedia/commons/a/a6/U%2B25C9.svg"/>
</div>

That way the whole grid container's width will not exceed what's necessary and one larger element won't screw layout . grid-template-columns will have to be set from JS though (since it depends on how many elements we have), but I guess it's unavoidable really ☹ )