Home > front end >  How do I make a responsive grid consisting of square images?
How do I make a responsive grid consisting of square images?

Time:02-27

On my website, I would like to add a grid consisting of square images (album covers). I also want to add this hover effect to said images: https://codepen.io/jarvis-ai/pen/GRJpQWO. How would I do this?

I have already tried a couple of things I found while researching my question but I never got the result I wanted. I have always had issues with the sizing of the images and making the sizes responsive. Here is a visualization of what I want it to look like and what I to happen:

  1. Grid on a normal-sized monitor:

Grid on a normal-sized monitor

  1. Grid on a smaller monitor or window:

Grid on a smaller monitor or window:

  1. Image on hover:

Image on hover

Pretty much: If the page is viewed on a normal-sized monitor, there should be 4 images in one row. If the page is viewed on a phone or if the window is resized, the images split into more rows with one row containing less than 4 now. If the mouse is being hovered over an image, the image should do the effect thing.

Notice: I should be able to do the hover effect by myself since there is already a working demo. I am just mentioning that I want the effect so that you can give me a solution that works with the effect.

Here is the last thing I have tried:

:root {
  --grey: grey;
  --white: white;
}

#music {
  width: 100%;
  min-height: 100vh;
  background-color: var(--grey);
  display: flex;
  color: var(--white);
  justify-content: center;
  align-items: center;
  text-align: center;
  flex-direction: column;
}

#cover-section {
  display: flex;
  align-items: center;
  vertical-align: middle;
  justify-content: center;
  flex-direction: row;
}

.cover {
  flex: 1 0 21%;
  width: 100%;
  height: auto;
  background-image: url(https://commons.wikimedia.org/wiki/File:Stack_Overflow_icon.svg);
}
<div id="music">
  <div id="cover-section">
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
    <div ></div>
  </div>
</div>

Thanks in advance for your help!

By the way: If I need JavaScript to achieve this, please do not tell me to just use JavaScript but give me some code I could use, as I have done next to nothing with JavaScript before.

CodePudding user response:

Something that works is that. I cant implement all the part you want, but for use this example in a mobile view use the media-query css.

Something to start, not a definitive solution! It would be expensive to do it all here.

This is the code:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

    <title>Document</title>
    <style>
        #music {
            width: 100%;
            height: 100vh;
            text-align: center;
            margin-top: 60px;

        }

        #cover-section {
            width: 100%;
            height: 100vh;
        }

        .b-game-card {
            width: 20%;
            height: 30%;
            float: left;
        }

        .cover {
            width: 90%;
            height: 90%;
            background: url('https://m.media-amazon.com/images/I/81aTawcGdmL._AC_SL1500_.jpg');
            background-size: cover;
            background-position: center;
            float: left;
        }
    </style>
</head>

<body>
    <div id="music">
        <div id="cover-section">
            <div >
                <div >
                </div>
            </div>
            <div >
                <div >
                </div>
            </div>
            <div >
                <div >
                </div>
            </div>
            <div >
                <div >
                </div>
            </div>
            
        </div>
</body>
<script>
    const maxTilt = 50; // Max card tilt (deg).

    $(".b-game-card")
        .mousemove(function (evt) {
            let bounding = mouseOverBoundingElem(evt);

            let posX = bounding.width / 2 - bounding.x;
            let posY = bounding.height / 2 - bounding.y;
            let hypotenuseCursor = Math.sqrt(Math.pow(posX, 2)   Math.pow(posY, 2));
            let hypotenuseMax = Math.sqrt(Math.pow(bounding.width / 3, 2)   Math.pow(bounding.height / 3, 2));
            let ratio = hypotenuseCursor / hypotenuseMax;

            $(".cover", this).css({
                transform: `rotate3d(${posY / hypotenuseCursor}, ${-posX / hypotenuseCursor}, 0, ${ratio * maxTilt}deg)`,
                filter: `brightness(${2 - bounding.y / bounding.height})`
            });
            $(".gloss", this).css({
                transform: `translateX(${posX * ratio * 1}px) translateY(${posY * ratio}px)`
            });
        })
        .mouseleave(function () {
            let css = {
                transform: "",
                filter: ""
            };
            $(".cover, .gloss", this).css(css);
        });

    function mouseOverBoundingElem(evt) {
        let bounding = evt.target.getBoundingClientRect();
        let x = evt.originalEvent.pageX - Math.round(bounding.left);
        let y = evt.originalEvent.pageY - Math.round(bounding.top);

        return {
            x: Math.max(0, x),
            y: Math.max(0, y),
            width: Math.round(bounding.width),
            height: Math.round(bounding.height)
        };
    }
</script>

</html>

CodePudding user response:

I managed to figure out a solution by myself. Here is the code:

HTML:

<div id="music">
    <div id="cover-section">
        <div >
            <!--Cover-->
        </div>
        <div >
            <!--Cover-->
        </div>
        <div >
            <!--Cover-->
        </div>
        <div >
            <!--Cover-->
        </div>
        <div >
            <!--Cover-->
        </div>
        <div >
            <!--Cover-->
        </div>
        <div >
            <!--Cover-->
        </div>
        <div >
            <!--Cover-->
        </div>
        <div  id="tablet-cover">
            <!--Cover-->
        </div>
    </div>
</div>

The tablet cover does not actually exist and is just a placeholder in case there are an uneven amount of squares in one row. As you can see in the...

CSS:

 #music {
  width: 100%;
  min-height: 100vh;
  background-color: var(--grey);
  display: flex;
  color: var(--white);
  justify-content: center;
  align-items: center;
  text-align: center;
  flex-direction: column;
}
#cover-section {
  display: flex;
  flex-wrap: wrap;
  width: 80%;
}

.cover {
  margin: 0px;
  flex: 1 0 21%;
  background-color: blue;
  border: 2px solid black;
}

#tablet-cover {
  display: none;
}

@media only screen and (max-width: 768px) {
  /* For phones: */
  .cover {
    flex: 1 0 41%;
  }
  #waving-hand span {
    font-size: 30pt;
  }
}

@media only screen and (min-width: 600px) and (max-width: 800px) {
  /* For tablets: */
  .cover {
    flex: 1 0 31%;
  }
  #tablet-cover {
    display: block;
  }
  #waving-hand span {
    font-size: 70pt;
  }
}

The tablet cover is being removed on smaller or larger screens, where there would be an even number of squares in one row. It gets added once there is an uneven amount of covers in a row so that the last row has two squares instead of two rectangles.

Now for the self-engineered JavaScript code:

let coverWidth = document.querySelector('.cover').offsetWidth;
const allCovers = document.getElementsByClassName('cover')
for (var i = 0; i < allCovers.length ; i  ){
    allCovers[i].style.height= coverWidth   "px";
}

function coverheight(){
    let coverWidth = document.querySelector('.cover').offsetWidth;
    const allCovers = document.getElementsByClassName('cover')
    for (var i = 0; i < allCovers.length ; i  ){
        allCovers[i].style.height= coverWidth   "px";
    }
}

window.onresize = coverheight;

This is what the code basically does:

  1. Check the width of the divs and then apply the value of the div-width to the height attribute of the divs
  2. Every time the screen is resized, it re-checks the values and sets the new values accordingly

I do not know if this code is the "cleanest" code, but as long as it works, I am happy. What sucks to me is that I had to work with media queries, because the flex layout is usually used for when you want a layout that is responsible by default, AFAIK.

Thanks to everyone who tried helping me out though! I hope I can help someone else with my spaghetti code.

  • Related