0

I am struggling to understand how CSS lays out elements on a page. This is a sketch of the layout I am trying to achieve: enter image description here

And inside canvas-column-1 I want to add a canvas element i.e it will be a child of canvas-column-1. However when I do this I find that this moves the position of canvas-column-2 which is sibling of canvas-column-1 so I anticipated it would not be affected by any child elements of its siblings: enter image description here

CSS:

:root {
  --header-height: 100px;
  --footer-height: 20px;
  --header-background: cornflowerblue;
  --column-1-width: 200px;
}

.header {
  height: var(--header-height);
  min-height: var(--header-height);
  max-height: var(--header-height);
  background-color: var(--header-background);
}

.main-content {
  min-height: calc(100vh - var(--header-height) - var(--footer-height));
  max-height: calc(100vh - var(--header-height) - var(--footer-height));
  min-width: 100vw;
  max-width: 100vh;
  width: 100vw;
  position: absolute;
  top: var(--header-height);
  left: 0;
  right: 0;
}

.footer {
  min-height: var(--footer-height);
  max-height: var(--footer-height);
  background-color: var(--header-background);
  position: absolute;
  top: calc(100vh - var(--footer-height));
  left: 0;
  right: 0;
}

.column-1 {
  min-width: var(--column-1-width);
  max-width: var(--column-1-width);
  width: var(--column-1-width);
  min-height: calc(100vh - var(--header-height) - var(--footer-height));
  max-height: calc(100vh - var(--header-height) - var(--footer-height));
  background-color: indianred;
  /* display: none; hidden and does NOT take up space. */
  /* -OR USE- */
  /* visibility: hidden; Hidden but still takes up space. */
  display: inline-block;
  position: absolute;
  top: 0;
  left: 0;
}

.column-2 {
  min-width: calc(100vw - var(--column-1-width));
  max-width: calc(100vw - var(--column-1-width));
  width: calc(100vw - var(--column-1-width));
  min-height: calc(100vh - var(--header-height) - var(--footer-height));
  max-height: calc(100vh - var(--header-height) - var(--footer-height));
  background-color: blueviolet;
  display: inline-block;
  position: absolute;
  top: 0;
  left: var(--column-1-width);
}

.canvas-column-1 {
  display: inline-block;
  min-width: 50%;
  max-width: 50%;
  width: 50%;

  min-height: calc(100vh - var(--header-height) - var(--footer-height));
  max-height: calc(100vh - var(--header-height) - var(--footer-height));
  height: calc(100vh - var(--header-height) - var(--footer-height));

  background-color: antiquewhite;
}

.canvas-column-2 {
  display: inline-block;
  min-width: 50%;
  max-width: 50%;
  width: 50%;

  min-height: calc(100vh - var(--header-height) - var(--footer-height));
  max-height: calc(100vh - var(--header-height) - var(--footer-height));
  height: calc(100vh - var(--header-height) - var(--footer-height));

  background-color: darkgray;
}

.left-canvas {
  width: 200px;
  height: 200px;
  border: 4px dashed darkblue;
}

HTML

<div>
  <div class="header" >This is the header</div>
  <div class="main-content">
    <div class="column-1"></div>
    <div class="column-2">
      <div class="canvas-column-1">Canvas Column 1
        <canvas #leftCanvas class="left-canvas" height="200px" width="200px"></canvas>
      </div>
      <div class="canvas-column-2">Canvas Column 2</div>
    </div>
  </div>
  <div class="footer" ></div>
</div>

I have used a lot of absolute positioning in mainly because I found that when it came to absolute positioning of canvas-column-1 and canvas-column-2 they would be relative to they also needed a non-static parent element otherwise they would not be positioned or sized correctly. Please note this example is for my understanding of how CSS positions and lays out elements.

This is a jsfiddle of the example but that renders something completely different again

D-Dᴙum
  • 7,689
  • 8
  • 58
  • 97
  • What do you mean by “I find that this moves the position of `canvas-column-2`”? What happens, specifically? – Pine Code Dec 26 '21 at 18:26
  • @PineCode `canvas-column-2` is moved down - the grey rectangle in the image in the question. I expected it to remain aligned vertically with the ivory `canvas-column-1` – D-Dᴙum Dec 26 '21 at 18:35

2 Answers2

1

I don't quit remember where i've read this in docs (i will look it up later), And I may not be remembering it correctly.

replaced elements dictates where the text line is in inline level layout, that is controlled with vertical-align property, which by default it is set to baseline, if you would change vertical-align on the appropriate element, it should fix it.

EDIT

The appropriate doc

The explanation

From the doc

A line box is always tall enough for all of the boxes it contains. However, it may be taller than the tallest box it contains (if, for example, boxes are aligned so that baselines line up). When the height of a box B is less than the height of the line box containing it, the vertical alignment of B within the line box is determined by the 'vertical-align' property.

Replaced elements don't actually dictates where the line is, But because they can be inline and sit next to text, and since they are generally taller than text that is why it pushed everything downward.

If you want you could decrease the height of the canvas and see the line moves upward.


There also a different issue with inline-block layout, which is that spaces and line breaks in the markup are not ignored, therefore manual calculations of available space won't work as expected.

You can read more about that How do I remove the space between inline/inline-block elements?


Here's a demo

Look at how .canvas-column-1 and .canvas-column-2 are not spaced out which fixes the issue with the column .canvas-column-2 not fitting on the same line.

:root {
  --header-height: 100px;
  --footer-height: 20px;
  --header-background: cornflowerblue;
  --column-1-width: 200px;
}

.header {
  height: var(--header-height);
  min-height: var(--header-height);
  max-height: var(--header-height);
  background-color: var(--header-background);
}

.main-content {
  min-height: calc(100vh - var(--header-height) - var(--footer-height));
  max-height: calc(100vh - var(--header-height) - var(--footer-height));
  min-width: 100vw;
  max-width: 100vh;
  width: 100vw;
  position: absolute;
  top: var(--header-height);
  left: 0;
  right: 0;
}

.footer {
  min-height: var(--footer-height);
  max-height: var(--footer-height);
  background-color: var(--header-background);
  position: absolute;
  top: calc(100vh - var(--footer-height));
  left: 0;
  right: 0;
}

.column-1 {
  min-width: var(--column-1-width);
  max-width: var(--column-1-width);
  width: var(--column-1-width);
  min-height: calc(100vh - var(--header-height) - var(--footer-height));
  max-height: calc(100vh - var(--header-height) - var(--footer-height));
  background-color: indianred;
  /* display: none; hidden and does NOT take up space. */
  /* -OR USE- */
  /* visibility: hidden; Hidden but still takes up space. */
  display: inline-block;
  position: absolute;
  top: 0;
  left: 0;
}

.column-2 {
  min-width: calc(100vw - var(--column-1-width));
  max-width: calc(100vw - var(--column-1-width));
  width: calc(100vw - var(--column-1-width));
  min-height: calc(100vh - var(--header-height) - var(--footer-height));
  max-height: calc(100vh - var(--header-height) - var(--footer-height));
  background-color: blueviolet;
  display: inline-block;
  position: absolute;
  top: 0;
  left: var(--column-1-width);
}

.canvas-column-1 {
  display: inline-block;
  min-width: 50%;
  max-width: 50%;
  width: 50%;
  min-height: calc(100vh - var(--header-height) - var(--footer-height));
  max-height: calc(100vh - var(--header-height) - var(--footer-height));
  height: calc(100vh - var(--header-height) - var(--footer-height));
  background-color: antiquewhite;
}

.canvas-column-2 {
  display: inline-block;
  min-width: 50%;
  max-width: 50%;
  width: 50%;
  min-height: calc(100vh - var(--header-height) - var(--footer-height));
  max-height: calc(100vh - var(--header-height) - var(--footer-height));
  height: calc(100vh - var(--header-height) - var(--footer-height));
  background-color: darkgray;
}

.left-canvas {
  width: 200px;
  height: 200px;
  border: 4px dashed darkblue;
}


 /* Solution */
.canvas-column-2{
  vertical-align:top;
}
<div>
  <div class="header">This is the header</div>
  <div class="main-content">
    <div class="column-1"></div>
    <div class="column-2">
    <div class="canvas-column-1">Canvas Column 1
        <canvas #leftCanvas class="left-canvas" height="200px" width="200px"></canvas>
      </div><div class="canvas-column-2">Canvas Column 2</div>
    </div>
  </div>
  <div class="footer"></div>
</div>
Rainbow
  • 6,772
  • 3
  • 11
  • 28
0

:root {
    --header-height: 100px;
    --footer-height: 20px;
    --header-background: cornflowerblue;
    --column-1-width: 200px;
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html, body, #container {
    height: 100%;
}

#container {
    display: flex;
    flex-direction: column;
    align-items: stretch;
}

.header {
    background-color: cornflowerblue;
}

.main-content {
    height: 100%;
    display: flex;
}

.footer {
    background-color: cornflowerblue;
    height: var(--footer-height);
}

.column-1 {
    background-color: indianred;
    flex: 1;
}

.column-2 {
    background-color: blueviolet;
    flex: 6;
    display: flex;
}

.canvas-column-1 {
    background-color: antiquewhite;
    flex: 1;
}

.canvas-column-2 {
    background-color: darkgray;
    flex: 1;
}

.left-canvas {
    width: 200px;
    height: 200px;
    border: 4px dashed darkblue;
}
<!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">
    <title>Document</title>
    <link rel="stylesheet" href="style.css">
</head>

<body>
    <div id="container">
        <div class="header">This is the header</div>
        <div class="main-content">
            <div class="column-1"></div>
            <div class="column-2">
                <div class="canvas-column-1">Canvas Column 1
                    <canvas #leftCanvas class="left-canvas" height="200px" width="200px"></canvas>
                </div>
                <div class="canvas-column-2">Canvas Column 2</div>
            </div>
        </div>
        <div class="footer"></div>
    </div>
</body>

</html>

enter image description here

Pine Code
  • 2,466
  • 3
  • 18
  • 43
  • Thanks for the suggestion but this doesn't explain why my example doesn't behave as I anticipated. Also the header is not the specified height, I suspect because of the use of flexbox? I want to avoid the use of flexbox because I have a specific layout I want to create and don't want it 'dynamically changing'. This is why I am experimenting with DIVs however I need to understand how positioning and layout work – D-Dᴙum Dec 26 '21 at 19:18