Let images go beyond the content area

If you insert images into a post or something similar, in most cases, they will have the maximum width of the text content. If the pictures are good, it can be cool to let them go beyond the width of the content area, for example from one border of the browser to the other in a one-column layout. This post shows you how to make this happen — as well in one-column as sidebar layout.

Update from March 18, 2017: Dave Rupert shows a more elegant way of full bleed elements in one-column layouts in hist post »Hassle-free Full Bleed with *:not()« which can be used instead of my proposed first solution. He uses the :not() selector to exclude elements from a max width. That can look like that (code from Dave’s post):

.post > *:not( img ):not( video ) {
    margin-left: auto;
    margin-right: auto;
    max-width: 50rem;
    padding-left: 5%;
    padding-right: 5%;
}

Images beyond the content area in one-column layouts

There are two possibilities for one-column layouts:

  1. You do not set a maximum width for the element which is wrapped around the content, but for every content element. For the images, you overwrite that value, so they are displayed wider.
  2. You set the width of the images with vw so that it can be displayed larger than the parent element.

Both solutions have advantages and disadvantages.

Maximum width directly for the content elements

The first solution’s CSS can look like that:

.entry-content > * {
    margin-left: auto;
    margin-right: auto;
    max-width: 800px;
}

.entry-content > .size-full {
    display: block;
    max-width: 100%;
}

The disadvantage of that:

  • We have to set a maximum width for every direct child element of .entry-content via .entry-content > *.

Advantages of that:

  • No browser-specific problems like with vw.
  • The image will not be scaled up beyond its natural size. That can be the case when using vw.

You can see a live example of this solution on CodePen.

Width in vw

The solution with vw can look like that:

.entry-content {
    margin-left: auto;
    margin-right: auto;
    max-width: 800px;
}

.entry-content .size-full {
    display: block;
    left: 50%;
    position: relative;
    transform: translateX(-50%);
    width: 100vw;
}

Disadvantages of that:

  • The image goes over the whole width of the viewport – no matter, if the viewport is 2,000 pixels wide and the image only 1,500 (I will explain how to prevent this shortly).
  • We need to center the image — in this example done with the cooperation of left, position and transform.
  • Browsers interpret 100vw differently. Firefox stretches the image over the whole width of the viewport, including the scroll bar. Because of that, you will get an extra horizontal scroll bar, and a few pixels of the image are not visible. Other browsers implemented 100vw as the width of the viewport without the scroll bar. If you use this solution, you have to use overflow-x: hidden; on the html element to hide the horizontal scroll bar.

The advantage of that:

  • We do not need to set a maximum width with the star selector but only for the container of the content elements.

Set image width as maximum width when using vw

The significant disadvantage of using vw is, in my opinion, that the image can be stretched beyond its natural size. For that, there is the following solution: We fetch the natural width from each image and set it as the max-width via inline styles. We pass the width of 100vw as inline styles too, so it only applies if adding the maximum width worked. Otherwise, the image will remain on the width of the content elements.

This is the solution:

{
    let fullWidthImages = document.querySelectorAll('.entry-content .size-full');
    if (fullWidthImages.length != 0) {
        for (let fullWidthImage of fullWidthImages) {
            let naturalWidth = fullWidthImage.naturalWidth;
            fullWidthImage.style.maxWidth = naturalWidth + 'px';
            fullWidthImage.style.width = '100vw';
        }
    }
}

We query all elements with the specified class and loop through the list. We get the actual width of the image with .naturalWidth and set this as the maximum width and 100vw as width. This solves the problem with the maximum width, but the problem with the partly hidden image in Firefox remains. For a one-column layout, I would prefer the first solution.

There is also a pen for the one-column solution with vw.

Images beyond the content area in sidebar layout

I am currently working on a theme which should let the user display images larger than the content area also in the sidebar layout. That can look like this:

Theoretically and with some calculation, we maybe could work here with the solution of setting a maximum width of the content elements, too. But I will only show a solution with vw. The starting point is a default two-column layout, with a wrapper which specifies the maximum width of main content and sidebar.

We need the earlier explained JavaScript to set the maximum width of the images. Instead of using 100vw for width, you should use 100% and specify this in the CSS file instead of inline. If the viewport becomes wider than the max width of the wrapper, you can set a breakpoint and specify a width for the images with calc(), so they become larger than the content area. You should also set a float: right; for the images, so they are getting larger on the left side. In the theme, the CSS looks like that:

@media screen and (min-width: 80em) {

    .sidebar-template .large-featured-image-template .wp-post-image {
        float: right;
        width: calc(100% + ((100vw - 1200px - 2.8rem) / 4));
    }

}

The wrapper reached its max width of 1,200 pixels, and I set the width of the images to the width of the content container (100%) and add roughly a quarter of the space, which remains on the left and right of the 1,200 pixels. So the image uses around half of the area, which is empty on the left beside the content.

Of course there is also a pen of this.

Related posts

Leave a Comment

Your email address will not be published. Required fields are marked *