Image layout test page
I want to experiment with wider layouts, so want to have HTML/CSS formulas for breaking out of the normal content flow.
House stylesPermalink to “House styles”
Copy-paste-able snippets for image arrangements.
One imagePermalink to “One image”
Two imagesPermalink to “Two images”
Three imagesPermalink to “Three images”
Multiple rowsPermalink to “Multiple rows”
Specify HeightPermalink to “Specify Height”
Blur stretch singlesPermalink to “Blur stretch singles”
Blur stretch doublesPermalink to “Blur stretch doubles”
This is possible, but didn’t always look that good, and would require more tweaking for images to resize aspect ratio-ally appropriately. See notes in
.eleventy.js @ the
WorkbookPermalink to “Workbook”
My process of working through getting the house styles.
Small, centeredPermalink to “Small, centered”
This image should be smaller than the main page flow, so should be centered.
The next one should also be smaller and centered.
Pixel densityPermalink to “Pixel density”
This image should display at 256. The source is 768. For displays that use higher pixel densities (e.g., retina displays, most phones), it should be crisp.
To compare two side-by-side, the following images are both displayed at 256 x 256 pixels, but their source images are:
- 256 x 256 pixels
- 768 x 768 pixels (i.e., exported @3x)
I use 3x for all higher-pixel-density images on this page simply because that’s best for my own devices. But devices should render any source / display ratio. E.g., here’s 0.5x, 2x, and 4x.
Text width image, pixel densityPermalink to “Text width image, pixel density”
Even without manually specifying a width (as we did in the above pixel density test), we expect the page width clamping to have the same effect, and higher pixel count images to be crisper.
The current full width of the layout is 704px.
The following image is 704 x 704 px, rendered at that size on the page.
The following image is 2112 x 2112 px, rendered at 704 x 704 px on the page.
We could go to 4x for future-proofing, but I think there is diminishing returns, even with devices.
Real image, pixel densityPermalink to “Real image, pixel density”
Deep dive into this in Image size test page
Full-width imagePermalink to “Full-width image”
This image will take up the full width of the page no matter what size the image or the page is. (My screen only goes up to 1680px width.) It will have no horizontal margins.
Full-width image, with horizontal marginsPermalink to “Full-width image, with horizontal margins”
See next section for technique notes. (These images aren’t width-limited, so they may go past 1500px width.)
Wider-than-text width centered imagePermalink to “Wider-than-text width centered image”
While the page width is ≤ the image width, this image will take up the full width of the page with no horizontal margin. Once the page is wider than the image, it will be centered in the page with equal horizontal margins.
We achieve the breakout by using the
.full-width CSS class designed for full-width images, but we instead put it on a parent
<div> to the image. This
<div> then takes up the full screen width, and the image is free to position inside it.
For a desired 3x pixel density (width px: src 3k, disp 1k), its width needs to be manually limited, or it will, by default, be displayed at its true “size” and a lower pixel density. This can be accomplished with the attribute
Wider-than-text width centered image, horizontal marginsPermalink to “Wider-than-text width centered image, horizontal margins”
… as needed as the page shrinks.
Max-width (centered) wider img, horizontal margins only on ~m+ sizesPermalink to “Max-width (centered) wider img, horizontal margins only on ~m+ sizes”
- small (phone): no H margins (want to see as much of photo as possible)
- medium: some H margins
- large: bigger than photo, so margins don’t matter
Three images arranged wider than textPermalink to “Three images arranged wider than text”
These each take up exactly 1/3:
We can add a horizontal page margin:
If we make them each take 33%, they distribute the remaining 1% of available width between them.
We can set their
max-width CSS so they are spaced more evenly when space is available.
This effect—using available spacing—is more readily visible with smaller images.
To get the images to stay closer to the center, you make the images
bare and add
justify-center flex. However, they then have no margin. Adding padding or margins works until the page shrinks so their widths are shrinking; then they balloon out past the page width with their extra margins/padding. To fix, I had to wrap them in
<div>s, then control the padding on the outside. Making the images proper (max) widths then involves a
calc() on the
<div>. Quite complex.
Turning up the padding is fine.
Be careful going down the rabbit hole of trying to get consistent horizontal page margins, though. Because of symmetric padding on the image LOL went down rabbit hole. Turns out switching to margins makes this somehow all work beautifully, and don’t even need
<div>s (which we need so the images are the same size and they aren’t shifted L or R on the page), combined with overall padding, we end up in 0.5 Tachyon units (I think).
calc() in the
max-widths, because we’re not affecting the image sizes now. (Next example still uses padding; house style uses margins.)
Regardless, we now have something that looks and works fine for 3 max-width’d imgs w/ some margins.
Seeking a “house style” below:
Testing this third house-style w/ larger images
Simplifying from later findings; I think we don’t need
w-third at all.
Portrait and landscape w/ “house style”Permalink to “Portrait and landscape w/ “house style””
The following isn’t working:
While margins are fine, and the heights all match up at full size, but the height of the first image is shrinking before the second.
Wild enough, removing the
<div> third/two-third widths fixed.
Mixed sizes with house stylePermalink to “Mixed sizes with house style”
Incredibly, this just works as well. My takeaway is to export things to be the same height and then let flexbox’s basic layout take it away.
Other little tricksPermalink to “Other little tricks”
display: block) so that divs don’t leave little bits of extra space apparently for descender elements
accordingly, then add
mv1when doing grids for vertical spacing
… and relatedly, don’t forget to add
novmarginto the images so that the margins can be controlled with the containing
RewrappingPermalink to “Rewrapping”
flex-wrap to the container gives us a simple wrap, where elements are wrapped as soon as the row can’t fit both at full size. We can add
novmargin to the images and
fig to the container if we want them to wrap closely (moving the vertical margin to the overall block).
Ideally, I’d want to be able to choose to wrap only when they’ve shrunk to a certain size. In other words, we don’t need the photos to be full size, but there might be a significantly smaller display size (like if it would only be 200px wide or something) for which we’d rather wrap.
This might be possible using
display: grid and
grid-template-columns: ..., but TBD still. A couple resources:
… or, wait, maybe we can just use a media query to only add
flex-wrap! Going from the house style below. Also needed to do margin adjustments: inter-pic margin is right only when not wrapped, and bottom when wrapped.
This isn’t perfect, because I think once the page width is less than even 600px or so, the photo get a bit too small, and this only wraps < 480px. But realistically, this will fix the other major viewing use case (phones), and all the media queries work exactly together, so I think it’s worth it.
Doing for 3 imgs too:
Height limitsPermalink to “Height limits”
I can’t ignore it: I probably implicitly designed for image heights that fit my viewport. Let’s think about limiting them.
Does this work for 2 imgs?
Wow, yes, it does beautifully… I guess I should just go for this? Only potential downside would be over-stretching for bigger screen devices. But honestly, being > CSSpx but < PHYSpx isn’t the end of the world, it’s already better than most photo displays people are going to encounter.
One more test: 1 img portrait.
I think the answer here is that “it depends on the design.” For almost all layouts, a portrait photo isn’t going to get that big. For laptop/desktop/ipad-in-landscape, the height caps the img, leaving lots of space in the width, and it goes with the flow. For a phone, the width caps it, since they’re so tall, and the photo only takes up ~1/2 of the screen. BUT, the one exception is the iPad in portrait mode. It’s exactly portrait-photo-size, so a big portrait photo will fill the whole thing.
That’s where the design part comes in. If it’s a nice photo, it could be really cool. If it’s kinda crummy, yeah, it’ll be a huge crummy photo. If you want to design around that for iPad users in portrait mode, then throw in a
min(100vh, 939px) or something. Otherwise, just keep
100vh and roll with it.
min(100vh, 939px)— general purposes. let images be seen in full, and also keep things at least @2x. wider displays will have photo sets nicely centered in the middle
939px— portrait images we want as bigger/establishing. this way smaller desktops will have it display larger (than the viewport height), and we’re keeping things crisp for ipads rather than having them blow up huge.
Varying Widths: Region FillingPermalink to “Varying Widths: Region Filling”
Ugh, the thing I didn’t want to address.
In some situations, this will happen inevitably as long as we’re limiting photo heights to viewport heights, and are unwilling to make surrounding photos more narrow (width-limited). Examples:
a portrait photo, then a landscape one
a landscape photo (height-limited), then two side-by-side photos (width-limited)
I’m still torn philosophically on limiting photos to viewport heights. I think I like it, at least for landscapes. For portraits where the aim is more establishing footage, I’m not so sure; they’d be so tiny on a poorly-dimensioned landscape-oriented screen.
I am pretty confident limiting side-by-side images to narrower widths is bad, though. They are already nearly too small at full-screen with full width access; much smaller and it’s basically pointless to have them.
Assuming I do end up with consecutive varying photo row widths, the main thing I can try is some background. Below contains a graveyard (in comments) of approaches, with one that finally worked:
- ❌ SVG-generated fractal noise (colors too random)
- ❌ BG gradient (manual + didn’t look good)
- ❌ BG gradient + alpha (manual, still didn’t look good)
- ❌ BG image, as addl. element, CSS blurred (could not get horizontal edges crisp)
- ❌ BG image, as parent. element, opacity w/
background-blend-mode(could not get blurring, didn’t look good without)
- ✅ BG image, as addl., element, blurred w/ SVG filter (hat-tip) (looks good, can re-use image, crisp edges). Implemented below:
However, now a new challenge arises: it’s too wide.
Varying Widths: Width Matching [draft]Permalink to “Varying Widths: Width Matching [draft]”
Because the photos are now all viewport height-limited, it’s possible for even side-by-side images to not take up the full width. This means that our new burred image background gets 100% page width when it shouldn’t.
Reading a bit about CSS Flexbox, it seems like it really only thinks row-by-row. When there’s a new flex row, it doesn’t know about the content above it. This seems to be a problem because I explicitly want my rows to be of equal width. CSS Grid is recommended for 2D layouts.
However, thinking a bit more, my constraints are kind of odd:
- the target width should be determined dynamically by the contents of the rows
- the target width will be the largest combined content width
- all rows will achieve this target width
- for rows whose content fills less than the target width
- the columns inside should spread to fill the remaining space proportionally
- the content should be centered
- the backgrounds will have blurred/semi-transparent versions of the images
- all items become 1 per row for smaller displays
- ideally, this is achieved with minimal manual markup
I can see why you’d want to simply design on a fixed-width grid.
Explicit image sizes: basicsPermalink to “Explicit image sizes: basics”
An age-old confusion of mine. Learning in the hopes I can use this to get lazy loading to work.
Takeaway: CSS instructions take priority over attribute dimensions with both are given.
NB: Here I’m using “pixels” to mean (a) CSS pixels when referring to the display, (b) true image pixels when referring to the image size.
No dimensions given; displays at original size:
Attribute dimensions match image dimensions; same:
Attribute dimensions do not match image dimensions; displays attribute dimensions:
Attribute dimensions do not match image dimensions, and do not match aspect ratio; displays attribute dimensions:
Attribute dimensions do not match image dimensions, but CSS style does; displays CSS style dimensions:
Attribute dimensions match neither image dimensions nor aspect ratio, but CSS style matches original (both dimensions and aspect ratio); displays CSS style dimensions:
Both attribute dimensions and CSS styles are different than original; displays CSS style dimensions:
CSS styles are different than original, but attribute dimensions match original; displays CSS style dimensions:
CSS style specifies non-pixel width (
100%) and no height, while attribute dimensions match original; displays CSS width, but attribute height:
CSS style specifies non-pixel width (
auto height, while attribute dimensions match original; displays CSS width, and height to match correct aspect ratio:
Explicit image sizes: into house stylesPermalink to “Explicit image sizes: into house styles”
Now, to go more flexible. This uses the house style, which breaks out of the normal margins using the following container.
<div class="full-width flex justify-center ph1-m ph3-l fig">
<!-- image goes here -->
Here’s a normal house-style image, whose dimensions are 2,718 x 2,718.
But if we add the size attributes with the true image size, it goes too wide or too narrow, always taking up
Can we fix it? If we add
width: auto to the CSS, it fixes the case of it going too wide, but it will still go too narrow. In other words, when the image is width-limited, it won’t then shrink the height.
aspect-ratioalone (w/o width spec) doesn’t fix anything vs original
aspect-ratiodoesn’t improve over
object-fit: containalmost works, ugh so close. it adds vertical whitespace above and below the image when it’s small (e.g., try 1/3 screen size). i guess it’s maintaining some kind of “box” that’s full size while resizing the image in it.
- also can’t get rid of
max-heightthough, even though
object-fit: containshould height limit as well (?)
- also can’t get rid of
width: auto; height: autoworks! but… is this really going to allow lazy loading now?