HTML/CSS and Flex : Position and size 3 elements according to rotations

Viewed 37

After a few days of research, I need your help regarding an integration problem that I encounter in HTML/CSS and Flex. I specify I'm not an expert in that domain.

I want to create an interface similar to a 2-dimensional orthonormal frame. So I would like to position and size 3 elements : an x ​​axis, a y axis, and a workspace.

Which is complicated is that the interface can be rotated in 4 different ways depending on the desired origin point (0; 0) : 0°, 90°, 180° and 270°.

Since pictures are worth a thousand words, here's what I'm looking to do exactly :

0° : enter image description here

90° : enter image description here

180° : enter image description here

270° : enter image description here

As you can see, if rotation is 0°, then the origin point is top left, if it's 90°, then top right, if it's 180°, then bottom right, if it's 270°, then bottom left.

I made several attempts, but none produced the expected result.

Do you have any simple implementation ideas/examples for this integration ?

Thanks !

See the description given above

1 Answers

As Paulie_D points out, grid is definitely the way to go here. Grid allows you to set up the basic layout. You can then set the widths and colours of the elements using css variables. These can be set by simply changing one of the classes in the grid container. I've put a basic skeleton together to show you how this can be done. I recommend reading the css-tricks article and watching this from Kevin Powell too. It's a good primer. Grid has a steep learning curve because there's a lot of options but it's worth the effort and once you know your way around, putting together kickass layouts becomes a lot easier.

function doBorder(orientation) {
  const gridElement = document.querySelector('.grid');
  const state = gridElement.getAttribute('data-state');
  gridElement.classList.remove(state);
  gridElement.classList.add(orientation);
  gridElement.setAttribute('data-state', orientation);
}
.grid {
  display: grid;

  --topbar-width:25px;
  --bottombar-width:25px;
  --sidebar-width-left:25px;
  --sidebar-width-right:25px;
  --corner-color:white;
  --content-color:gray;
  --default-bar-color:red;
  --topbar-color:var(--default-bar-color);
  --sidebar-left-color:var(--default-bar-color);
  --sidebar-right-color:var(--default-bar-color);
  --bottombar-color:var(--default-bar-color);

  width:80vw;
  height:80vh;
  grid-template-columns: var(--sidebar-width-left) 1fr var(--sidebar-width-right);
  grid-template-rows: var(--topbar-width) 1fr var(--bottombar-width);

  grid-template-areas:
    "topcornerleft topbar topcornerright"
    "sidebarleft content sidebarright"
    "bottomcornerleft bottombar bottomcornerright";
}

.topbar {
  grid-area: topbar;
  background-color:var(--topbar-color);
}

.sidebarleft {
  grid-area: sidebarleft;
  background-color:var(--sidebar-left-color);
}

.sidebarright {
  grid-area: sidebarright;
  background-color:var(--sidebar-right-color);
}

.bottombar {
  grid-area: bottombar;
  background-color:var(--bottombar-color);
}

.topcornerleft {
  grid-area:topcornerleft;
  background-color:var(--corner-color);
}

.topcornerright {
  grid-area:topcornerright;
  background-color:var(--corner-color);
}

.bottomcornerleft {
  grid-area:bottomcornerleft;
  background-color:var(--corner-color);
}

.bottomcornerright {
  grid-area:bottomcornerright;
  background-color:var(--corner-color);
}

.topcornerleft, .topcornerright, .bottomcornerleft, .bottomcornerright {
  background-color: var(--corner-color);
}

.content {
  background-color: var(--content-color);
  grid-area: content;
}

.state0 {
  --sidebar-width-right:0;
  --bottombar-width:0;
  --sidebar-left-color:blue;
}

.state90 {
  --sidebar-width-left:0;
  --bottombar-width:0;
  --topbar-color:blue;
}

.state180 {
  --topbar-width:0;
  --sidebar-width-left:0;
  --sidebar-right-color:blue;
}

.state270 {
  --topbar-width:0;
  --sidebar-width-right:0;
  --bottombar-color:blue;
}
<div class="grid state0" data-state="state0">
  <div class="topcornerleft"></div>
  <div class="topbar"></div>
  <div class="topcornerright"></div>
  <div class="sidebarleft"></div>
  <div class="content">
    <input type="radio" name="radio1" id="top" onclick="doBorder('state0')" checked="true"><label for="top">Top</label>
    <input type="radio" name="radio1" id="left" onclick="doBorder('state90')"><label for="left">Left</label>
    <input type="radio" name="radio1" id="right" onclick="doBorder('state180')"><label for="right">Right</label>
    <input type="radio" name="radio1" id="bottom" onclick="doBorder('state270')"><label for="bottom">Bottom</label>
  </div>
  <div class="sidebarright"></div>
  <div class="bottomcornerleft"></div>
  <div class="bottombar"></div>
  <div class="bottomcornerright"></div>
</div>

Related