What are the steps to effectively cultivate an isometric rectangular box using HTML and CSS?

Starting at the top in isometric grids, like this, can be quite convenient: https://i.sstatic.net/YFh0SRmx.jpg

The code below is used to create a "3d" isometric box:

body {
  display: flex;
  justify-content: center;
  align-items: center;
}

.plane {
  position: relative;
  width: 600px;
  height: 600px;
}

.container {
  position: absolute;
  width: 0;
  height: 0;
}

.left {
  background-color: #3e8fe1;
  height: var(--width);
  width: var(--height);
  transform-origin: 0 0;
  transform: rotate(90deg) skewX(-30deg) scaleY(0.864);
}

.right {
  position: relative;
  background-color: #2870bd;
  height: var(--height);
  width: var(--length);
  transform-origin: 0 0;
  transform: rotate(-30deg) skewX(-30deg) scaleY(0.864);
  bottom: var(--width);
}

.top {
  position: relative;
  background-color: #80bdfe;
  height: var(--length);
  width: var(--width);
  transform-origin: 0 0;
  transform: rotate(210deg) skew(-30deg) scaleY(0.864);
  bottom: calc(var(--width) + var(--height));
}
<body>
  <div class="plane">
    <div class="container" style="--width: 50px; --length: 200px; --height: 100px; left: 150px; top: 150px;">
      <div class="left"></div>
      <div class="right"></div>
      <div class="top"></div>
    </div>
  </div>
</body>

While the current setup works, is there a way to tweak it so that increasing the --width, --length, and --height CSS variables would expand the box in the opposite directions?

In other words, can we make --width extrude towards you as it grows, instead of away from you as it currently does?

Similarly, increasing --height should cause the box to grow upwards instead of downwards.

Lastly, increasing --length should make the box extend towards the "camera", not away from it as it does now.

Answer №1

If you simply adjust the rotation value to value - 180 and make some tweaks to the translate transformation, you will see it expanding in the opposite direction:

const wrapper = document.getElementById('wrapper')
const width = document.getElementById('width')
const length = document.getElementById('length')
const height = document.getElementById('height')

width.addEventListener("input", (event) => {
  wrapper.style.setProperty("--w", `${event.target.value}px`)
})

length.addEventListener("input", (event) => {
  wrapper.style.setProperty("--l", `${event.target.value}px`)
})

height.addEventListener("input", (event) => {
  wrapper.style.setProperty("--h", `${event.target.value}px`)
})
body {
  display: flex;
  justify-content: center;
  align-items: center;
}

.square {
  position: relative;
  width: 500px;
  height: 500px;
}

.wrapper {
  position: absolute;
  width: 0;
  height: 0;
}

.left-side {
  background-color: #3e8fe1;
  height: var(--w);
  width: var(--h);
  transform-origin: 0 0;
  transform: translate(calc(var(--l) * -0.864), calc(var(--l) / 2)) rotate(270deg) skewX(-30deg) scaleY(0.864);
  position: relative;
}

.right-side {
  position: relative;
  background-color: #2870bd;
  height: var(--h);
  width: var(--l);
  transform-origin: 0 0;
  transform: translate(calc(var(--w) * 0.864), calc(var(--w) / -2)) rotate(150deg) skewX(-30deg) scaleY(0.864);
}

.top-side {
  position: relative;
  background-color: #80bdfe;
  height: var(--l);
  width: var(--w);
  transform-origin: 0 0;
  transform: rotate(30deg) skew(-30deg) scaleY(0.864);
  bottom: calc(var(--h) + var(--h) + var(--w));
}
<div class="square">
  <div id="wrapper" class="wrapper" style="--w: 50px; --l: 200px; --h: 100px; left: 150px; top: 150px;">
    <div class="left-side"></div>
    <div class="right-side"></div>
    <div class="top-side"></div>
  </div>
</div>

<div style="position: fixed;
    top: 0;
    right: 0;
    z-index: 999999;">
  Width: <input type="range" min="10" max="400" value="50" class="slider" id="width">
  <br/> Length: <input type="range" min="10" max="400" value="200" class="slider" id="length">
  <br/> Height: <input type="range" min="10" max="400" value="100" class="slider" id="height">
</div>

Important: The constant in the translate is set as 0.864, but feel free to adjust it based on the scale value (also set as 0.864).

Answer №2

Incorporating translation in the transform line proved to be a pivotal move for me, enabling a counter-movement and face realignment on the cube. A striking realization dawned upon me when I observed your use of three separate divs in the example; hence, I opted to replace two of them with before and after pseudo-elements.

body {
  background-color: #000;
  box-shadow: inset 0 0 1em #000;
}

#plane {
  width: 10em;
  height: 10em;
  margin: 0 auto;
  position: relative;
  top: 5em;
  transform: rotateX(45deg) rotateZ(45deg) translateZ(-1em);
  transform-style: preserve-3d;
}

#plane div {
  float: left;
  transform-origin: 97% 97%;
  position: relative;
}

.tall {
  background: #fff;
  transform: translateZ(var(--height));
  transform-style: preserve-3d;
  width: var(--width);
  height: var(--length);
}

.tall:before, .tall:after {
  content: "";
  background: #2e6b8f;
  position: absolute;
  transform-origin: 100% 100%;
}

.tall:before {
  transform: translateY(calc(var(--length) - 1em - var(--height) + 1em)) rotateX(90deg);
  box-shadow: inset 0em -.125em .25em rgba(0, 0, 0, .1);
  width: var(--width);
  height: var(--height);
}

.tall:after {
  transform: translateX(calc(var(--width) - 1em - var(--length) + 1em)) translateY(calc(var(--length) - 1em)) rotateX(90deg) rotateY(90deg) translateX(calc(var(--height) * -1 + 1em));
  box-shadow: inset -.125em 0em .25em rgba(0, 0, 0, .1);
  width: var(--length);
  height: var(--height);
}
<div id="plane">
  <div class="tall" style="--width: 1em; --length: 1em; --height: 5em"></div>
  <div class="tall" style="--width: 1em; --length: 1em; --height: 4em"></div>
  <div class="tall" style="--width: 1em; --length: 1em; --height: 3em"></div>
  ...
  (additional HTML code removed for brevity)
  ...
</div>

Answer №3

Do you have a specific motive for restricting yourself to CSS+HTML? It would be quite easy to replicate this with a tool such as Isomer.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Struggling to activate the hide/show feature on mouseover

After exploring different methods and seeking guidance on this platform, I am still unable to achieve the desired outcome. My goal is to have the content in the "topb" section appear when hovering over a link with the class of "top" and disappear when the ...

CSS: Troubles with Element Widths

I'm dealing with a list item that contains an image, like so: <ul> <li> <img></img> </li> </ul> The image is not filling the entire width of the list item. Is there a way to make the list item shr ...

The div container is not expanding to full width on mobile screens when using Next.js and Tailwind CSS

My goal is to make my div stretch or go full width similar to the table on my page. I have experimented with max-w-full, w-screen, and w-full, but the div is not extending all the way... https://i.stack.imgur.com/8BJnI.png This is the code for my page. ...

What are the steps to shift columns to the left within a table?

I need to adjust the alignment of the columns and also create a fixed size space between them. Currently, it appears like this: https://i.sstatic.net/F7Rqk.png My desired outcome is something similar to: https://i.sstatic.net/ALKa9.png CSS Code: .tabl ...

When an image is loaded, use Jquery to automatically open a new tab, instead of

I need to implement a function where, on loading an image on a page, a new tab opens and starts downloading a file from a specific URL while keeping the original page open. This task is part of a WordPress site with a jQuery section in the backend. I' ...

Tips for saving Web page changes permanently

After tweaking the background color and fonts on a website, I want these changes to stick for future visits. However, every time I refresh the site, it reverts back to its original design. Is there a way to make these modifications permanent, whether usin ...

HTML and CSS - Aligning text and managing scrollbar visibility

I am currently diving into the world of coding and embarking on the journey of crafting a website for my father. This project not only helps me gain valuable experience but also builds up my portfolio. Utilizing unsemantic and normalize frameworks, I enco ...

Troubleshooting IE8 Problem with CSS Table Cell

Wondering if this is an easy fix :) I have a website with the following CSS styles: .gameboard-table { border: solid 3px black; padding: 0px; border-collapse: collapse; } .gameboard-table tr { padding: 0px; margin: 0px; } .gameboard- ...

Tips for creating a button that maintains consistency across different screen sizes

One of the images linked below shows a button displayed on two different sized screens, one 24 inches and the other 13 inches. The button on the 24-inch display appears normal, while the "Add to Cart" button on the 13-inch display is broken. Check out th ...

What is the best method for users to add a div element and its contents?

As someone new to the world of web development, I am currently learning and working on a project. I have encountered an issue with creating a custom div that includes a link and user-defined text. I want the div to be generated automatically when the use ...

What is the proper way to encode image URLs for use in CSS?

For the div element in my code, I want to allow users to input a URL that will be applied as a CSS background image, like this: background-image: url("/* user specified URL here*/") I'm concerned about security. How can I properly escape the URL to ...

Struggling with adding a border to an HTML table?

I am attempting to create a table with alternating borders on the cells. After trying the code below, I still can't seem to get the desired effect. The borders are not showing up at all. Can someone provide guidance on how to achieve this? <style ...

In next js, the component exceeds 100% overflow when padding is added

https://i.sstatic.net/W30tk.png Hey there, I've been encountering some issues with next js and styled-components. I have a parent component (sc-hgRfpC lbMBdR) with a width of 400px, and swap-div-5 with a width: 100%. However, when I add padding: 12px ...

Determining the cursor location within a character in a div that is content editable using AngularJS

I am facing challenges with obtaining the cursor caret position within a contenteditable div. Currently, I am utilizing the following function : onBlurArea (field, ev) { ev.preventDefault() const editable = ev.target.childNodes[1].childNodes[2] ...

Unable to designate a particular value to a variable

For a recent project, I was tasked with implementing servlet handling to calculate the net pay salary of an employee based on user input. While most of the information was processing correctly, I encountered an issue when attempting to determine the rate. ...

Text in Bootstrap Carousel shifting during transition to active item

I'm encountering a problem similar to the one discussed in this thread about Bootstrap Carousel Caption movement after transition. Despite reading and attempting the solutions provided, I still haven't been able to resolve my issue... In my case ...

tables that are intertwined

There are three tables on my page and they are all overlapping. Is there a way to prevent this overlap? Check out this link <table id="inventoryTable" class="table dataTable" aria-describedby="inventoryTable_info"> <thead& ...

Can you propose a different approach to creating the "word stack" that overcomes the limitations of my current method?

I am attempting to convert a set of two radio buttons into a stack of two labels, one blue and one gray, to represent the selected radio button and the unselected one. Clicking on this stack will toggle which label is blue (and consequently which radio but ...

Selecting the first child within a table using the first-child

I recently set up a login portal page for three different websites. The layout consists of three separate login portals displayed neatly in two columns within a table named "loginPortals". I am currently working on styling the page using CSS, aiming to enh ...

Showing the Length of Several Videos Simultaneously on a Webpage

I am attempting to showcase the "duration" for each video on the page using JavaScript. This is my current code: var vid = document.querySelector(".mhdividdur"); vid.onloadedmetadata = function() { var x = document.querySelector(".mhdividdur").duratio ...