Ashton C Montgomery

Web Developer

Small House: Building More Realistic Structures with CSS

As part of my journey in learning and experimenting with 3D CSS, I decided to take on the challenge of creating a more realistic building structure. The goal of the small house project was to build a simple house that looked more like a real structure, with transparent windows and walls that truly resembled a physical object. This project involved a lot of planning and problem-solving, but it provided valuable lessons in CSS manipulation and how to create more dynamic, lifelike web elements.

Project Overview

The core idea behind the small house project was to make the walls and windows more realistic. To do this, I split each wall into smaller blocks, which allowed me to make the windows transparent panes. This approach gave the illusion of being able to look through the windows, rather than simply layering the window on top of the wall div, which would block the view.

Approach & Execution

This project involved loads of planning, especially in terms of how to lay out the structure. The planning process was similar to what I did with the 3D Moving Block Name project, where I drew out each element in a grid to determine the ideal width and height for each part of the design.

Key Steps:

  1. Wall Division and Window Placement: I began by splitting the walls of the house into smaller blocks. This allowed me to position the windows as transparent panes that could be seen through, creating a more realistic look.

  2. Object-Based Calculation: To manage all the wall types and ensure each section of the house was built properly, I stored all necessary calculations in an object. This object contained the data needed to determine how many blocks each wall needed based on its size and shape.

    let house = {
    twoWindowWithEntrance: { // 8em wide side
    tallPillar: 6,
    mediumWideBlock: 4,
    windowPane: 8,
    frontEntranceWindowPane: 2,
    frontEntranceWindowTrim: 4,
    door: 1,
    doorHandlePlate: 1,
    doorHandle: 1,
    frontEntranceTop: 1
    },
    threeWindowNoEntrance: { // 8em wide side
    tallPillar: 6,
    tallColumn: 2,
    mediumWideBlock: 6,
    windowPane: 12
    },
    largeWindow3PaneSmall: { // 4em wide side
    tallPillar: 3,
    tallColumn: 1,
    block: 2,
    windowPane: 6
    },
    highWindowSmall: { // 4em wide side
    tallPillar: 2,
    wideBlock: 4,
    windowPane: 4
    }
    }

  3. Triangular Room Sections: For the triangular pieces of the room, I had to use some advanced techniques like masking to hide parts of the div and then rotate and position the sides of the box to complete the form. This was a bit tricky but helped create a more realistic interior shape for the house.

    .roof {
    transform: translate3d(0, -3em, 0);

    .largeSideOfRoof:nth-child(1) {
    transform: translate3d(0, 0.0625em, 1.425em) rotateX(var(--roofPitch));
    }
    .largeSideOfRoof:nth-child(2) {
    transform: rotateY(180deg) translate3d(0, 0.0625em, 1.425em) rotateX(var(--roofPitch));
    }
    .smallSideOfRoof:nth-child(3) {
    transform: rotateY(90deg) translate3d(0, 0, 3.75em);
    }
    .smallSideOfRoof:nth-child(4) {
    transform: rotateY(-90deg) translate3d(0, 0, 3.75em);
    }
    .smallSideOfRoof .front,
    .smallSideOfRoof .back {
    clip-path: polygon(0 100%, 50% 0, 100% 100%);
    }
    .smallSideOfRoof .right {
    transform: rotateZ(-51.5deg) rotateY(90deg) translate3d(0, -.25em, 1.875em);
    height: var(--slope);
    }
    .smallSideOfRoof .left {
    transform: rotateZ(51.5deg) rotateY(90deg) translate3d(0, 0.25em, -2.2em);
    height: var(--slope);
    }
    .smallSideOfRoof .top {
    visibility: hidden;
    }
    }

    The .smallSideOfRoof sections are where you will see the clip-path masking and additional sizing and rotation to the sides to complete the formation of the side boxes of the roof.

  4. Function Creation: I created functions to generate the required number of blocks for each wall type. This made it easier to handle the large-scale layout and ensured that each wall type was correctly represented in the final design.

    let twoWindowWithEntrance = document.getElementsByClassName("twoWindowWithEntrance");
    twoWindowWithEntrance.innerHTML = "";
    let threeWindowNoEntrance = document.getElementsByClassName("threeWindowNoEntrance");
    threeWindowNoEntrance.innerHTML = "";
    let largeWindow3PaneSmall = document.getElementsByClassName("largeWindow3PaneSmall");
    largeWindow3PaneSmall.innerHTML = "";
    let highWindowSmall = document.getElementsByClassName("highWindowSmall");
    highWindowSmall.innerHTML = "";

    function setBlocks() {
    let sideTypes = Object.keys(house);
    console.log(sideTypes);
    for (let i = 0; i < sideTypes.length; i++) {
    if (sideTypes[i]) {
    let blockTypes = Object.keys(house[sideTypes[i]]);
    let blocksWithAmounts = house[sideTypes[i]];
    console.log(sideTypes[i] + " required block types are " + blockTypes);
    console.log(blocksWithAmounts);
    for (let j = 0; j < blockTypes.length; j++) {
    for (k = 0; k < house[sideTypes[i]][blockTypes[j]]; k++) {
    if (sideTypes[i] == "twoWindowWithEntrance") {
    for (let l = 0; l < twoWindowWithEntrance.length; l++) {
    twoWindowWithEntrance[l].innerHTML += "div class=\"block "+ blockTypes[j] + "\"/div";
    console.log(blockTypes[j] + " was added to " + sideTypes[i] + " " + l);
    }
    } else if (sideTypes[i] == "threeWindowNoEntrance") {
    for (let l = 0; l < threeWindowNoEntrance.length; l++) {
    threeWindowNoEntrance[l].innerHTML += "div class=\"block "+ blockTypes[j] + "\"/div";
    console.log(blockTypes[j] + " was added to " + sideTypes[i] + " " + l);
    }
    } else if (sideTypes[i] == "largeWindow3PaneSmall") {
    for (let l = 0; l < largeWindow3PaneSmall.length; l++) {
    largeWindow3PaneSmall[l].innerHTML += "div class=\"block "+ blockTypes[j] + "\"/div";
    console.log(blockTypes[j] + " was added to " + sideTypes[i] + " " + l);
    }
    } else if (sideTypes[i] == "highWindowSmall") {
    for (let l = 0; l < highWindowSmall.length; l++) {
    highWindowSmall[l].innerHTML += "div class=\"block "+ blockTypes[j] + "\"/div";
    console.log(blockTypes[j] + " was added to " + sideTypes[i] + " " + l);
    }
    } else {
    console.log("Error: side type wasn't found.")
    }
    }
    }
    }
    }
    }

    I set the set the sides for each block using the same function used in City Scene #2, "setSides".

  5. Expanding to Larger Structures: After completing the small house, I was eager to expand on the design. I began adding more wall sections and even started building a larger house. However, as I delved deeper into the project, I realized I needed to pivot my focus to other areas of my web development journey to continue growing.

Final Thoughts

The small house project was a rewarding exercise in CSS manipulation and building more realistic structures. The planning phase was intensive, but it helped me develop a better understanding of how to use CSS to create more dynamic and lifelike designs. The challenges I encountered along the way, especially with the triangular room sections and transparent windows, pushed me to think outside the box and apply creative solutions.

While I did not finish building an entire large house, the skills I gained in this project were invaluable. Moving forward, I may find myself tinkering on it as a passion project, but needed to focus my attention on other aspects of web development to further my journey.

Need Help Shaping Your Corner of the Internet?

I'd love to work with you.

Off to the Contact Page!