Search code examples
htmlcss

How to reserve space for responsive img (stop blocks jumping down)


How to solve a problem of jumping down blocks after image load if image should be responsive?

Codesandbox.

Info:

  • Image should shrink on window resize
  • Image max-width is it's own width
  • We don't know image size
  • JS can be used

Idea:

If it's not possible without any image size data, then can it be done only with image aspect ratio?

If you know image aspect ratio, you can calculate block height and put responsive image inside with some unused space (at least unused space will be not big on small window size).

Image loading: enter image description here

Image loaded: enter image description here

Html:

import React from "react";
import "./styles.css";

const img =
  "https://s3.amazonaws.com/images.seroundtable.com/google-css-images-1515761601.jpg";

export default function App() {
  return (
    <div className="app">
      <img alt="" src={img + `?${Date.now()}`} className="img" />
      <h1>I always jump down :(</h1>
    </div>
  );
}

CSS:

.app {
  box-sizing: border-box;
}
.img {
  max-width: 100%;
}
h1 {
  background-color: red;
}

Solution

  • AS @DBS said, it seems that only solution is to wrap image in div block with calculated height based on window.width and aspect ratio (in my case i know it). If there is any better solutions, don't hesitate to answer.

    Sandbox solution example.

    import React from "react";
    import "./styles.css";
    import styled from "styled-components";
    
    const aspectRatio = [1, 5];
    
    const img =
      "https://s3.amazonaws.com/images.seroundtable.com/google-css-images-1515761601.jpg";
    
    export default function App() {
      return (
        <div className="app">
          <StyledDiv>
            <img alt="" src={img + `?${Date.now()}`} className="img" />
          </StyledDiv>
    
          <h1>I always jump down :(</h1>
        </div>
      );
    }
    
    const StyledDiv = styled.div`
      height: calc(100vw / ${aspectRatio[1]});
      overflow-y: hidden;
    `;