skip to Main Content

I am trying to make my portfolio website better looking by adding throwing some images in the background at random positions but is is not working as expected. This is what I have:
//This is the index.html page:

<!-- header and navbar above of the webpage above-->

<body>
    <!--==================== Background Random Images ====================-->
   <div class="image-container">
        <img src="https://shorturl.at/T8cGm"
            alt="Image 1">
        <img src="https://shorturl.at/T8cGm"
            alt="Image 2">
        <img src="https://shorturl.at/T8cGm"
            alt="Image 3">
        <img src="https://shorturl.at/T8cGm"
            alt="Image 1">
        <img src="https://shorturl.at/T8cGm"
            alt="Image 2">
        <img src="https://shorturl.at/T8cGm"
            alt="Image 3">
    </div>
   <!-- hero, cta, footer sections of the webpage below-->
</body>

//This is the css:

.image-container {
    position: relative; 
    width: 100%; 
    height: 100vh; 
    overflow: hidden; 
}
.image-container img {
    position: absolute;
    transition: width 0.2s, height 0.2s; 
    width: 100px;
    height: 100px;
} 

//and this is the js:

document.addEventListener("DOMContentLoaded", function () {
    const imageNodeList = document.querySelectorAll(".image-container img");
    const imageArray = Array.from(imageNodeList);

    const maxAttempts = 100; // Maximum number of attempts to find a non-overlapping position
    const resizeFactor = 0.9; // Factor by which to reduce the size on each resize attempt

    function setPositions(images, positions) {
        images.forEach((img, index) => {
            img.style.left = `${positions[index].left}px`;
            img.style.top = `${positions[index].top}px`;
        });
    }

    function getRandomPos(maxWidth, maxHeight, imgWidth, imgHeight) {
        const randomX = Math.floor(Math.random() * (maxWidth - imgWidth));
        const randomY = Math.floor(Math.random() * (maxHeight - imgHeight));
        return { left: randomX, top: randomY };
    }

    function isOverlapping(pos, positions, imgWidth, imgHeight) {
        return positions.some(p => {
            return !(
                pos.left + imgWidth < p.left || // Right of new image is left of existing image
                pos.left > p.left + p.width ||  // Left of new image is right of existing image
                pos.top + imgHeight < p.top ||  // Bottom of new image is above existing image
                pos.top > p.top + p.height      // Top of new image is below existing image
            );
        });
    }

    function positionImages(images) {
        const newPositions = [];
        images.forEach(img => {
            let pos;
            let attempts = 0;
            let resized = false;

            while (attempts < maxAttempts) {
                pos = getRandomPos(window.innerWidth, window.innerHeight, img.width, img.height);
                if (!isOverlapping(pos, newPositions, img.width, img.height)) {
                    newPositions.push({ ...pos, width: img.width, height: img.height });
                    break;
                }
                attempts++;
            }

            if (attempts >= maxAttempts) {
                // Resize and retry positioning
                img.width *= resizeFactor;
                img.height *= resizeFactor;
                console.warn('Resizing image due to overlapping');
                positionImages([img]); // Retry positioning this image
            }
        });

        setPositions(images, newPositions);
    }

    positionImages(imageArray);
});

What I intended to do:

  1. Scatter these images in the background at random positions without them interfering with elements of the webpage.
  2. Scatter them to the whole page from "hero section" to "contact section"
    Here is the github of the repo if you want to look into it in detail:
    [https://github.com/faizalkhan99/Portfolio]

When all this is isolated, it works perfectly as shown below:
Isolated code

BUT when I merge this into my main file, it just sits at the top of the page:
merged into main portfolio's index.html

2

Answers


  1. You just need to set the position of your .image-container to fixed, so that no space is allocated for it in the DOM and it stays at the top of the window (does not scroll with the content).

    After trying it on your actual webpage, I noticed that the images cover some of your content. Setting the z-index to -10 fixed that.

    .image-container {
        position: fixed; 
        z-index: -10;
        top: 0px; /* Only needed if image-container is not at top of body  */
    
        width: 100%; 
        height: 100vh; 
        overflow: hidden; 
    }
    
    Login or Signup to reply.
  2. As you want the images to always cover the full background, change the position of image-container to absolute and add top and left to 0 to define from where the component should start.

    The below css works fine when adding the image rendering tags at the last of the DOM, if the tags are at the start of the DOM then you need to change the css for the other content to position absolute.

    .image-container {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%; 
        height: 100vh; 
        overflow: hidden; 
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search