Search code examples
cssflexboxcss-grid

How can I create such a block using flex or grid?


I want to create a block that contains 3 main elements: a header, a list, and a chart. When the screen width drops below a certain value, I want the order of the elements to change. Here's how it should look: enter image description here

Here are the requirements:

  • .chart should have a minimum height.
  • .chart__datasets can have any height depending on the number of items.
  • .chart__canvas should always maintain a 1:1 aspect ratio (only on large screens).
  • .chart__datasets and .chart__canvas should always be horizontally centered within the block.
  • .chart__datasets should take up 70% of .chart width, and the .chart__canvas 30%.
  • There should be at least a 20px gap between the .chart__header and the .chart__datasets.

I have created a basic layout. I used flex for everything. The header has position: absolute, and I wrapped the list and the chart in a div with the class chart__body and centered them relative to each other within it. But there's an issue: if the list (dataset) has a large height, it starts overlapping with the header, and I don't know how to fix this yet.

html, body, .page {
  height: 100%;
}

body {
  margin: 0;
}

.page {
  display: flex;
  align-items: center;
  justify-content: center;
  background: #ecf0f1;
}

.chart {
  width: 450px;
  padding: 15px 15px;
  min-height: 200px;
  display: flex;
  flex-direction: column;
  position: relative;
  background: #fff;
  border: 1px solid #7f8c8d;
}

.chart__title {
  position: absolute;
  top: 0;
  left: 15px;
  background: #3498db;
  width: 50%;
  height: 25px;
}

.chart__body {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  flex-grow: 1;
  column-gap: 15px;
}

.chart__datasets {
  width: 70%;
  height: 50px;
  background: #f1c40f;
}
  
.chart__canvas {
  background: #2ecc71;
  width: 100px;
  height: 100px;
}

@media (max-width: 600px) {
  .chart__body {
    margin-top: 60px;
    flex-direction: column-reverse;
    align-items: normal;
    row-gap: 15px;
  }
  .chart__datasets {
    width: 100%;
    flex-grow: 1;
  }
  .chart__canvas {
    width: 100%;
    height: 50px;
  }
}
<div class="page">
<div class="chart">
  <h3 class="chart__title"></h3>
  <div class="chart__body">
    <div class="chart__datasets">
      
    </div>
    <div class="chart__canvas">
    
    </div>
  </div>
</div>
</div>


Solution

  • Don’t absolutely position your title.

    After running this snippet, use the full page link to test it.

    html, body, .page {
      height: 100%;
    }
    
    body {
      margin: 0;
    }
    
    .page {
      display: flex;
      align-items: center;
      justify-content: center;
      background: #ecf0f1;
    }
    
    .chart {
      width: 450px;
      padding: 15px 15px;
      min-height: 200px;
      display: flex;
      flex-direction: column;
      background: #fff;
      border: 1px solid #7f8c8d;
    }
    
    .chart__title {
      background: #3498db;
      width: 50%;
      height: 25px;
      margin-top: 0;
    }
    
    .chart__body {
      width: 100%;
      height: 100%;
      display: flex;
      align-items: center;
      flex-grow: 1;
      column-gap: 15px;
      padding-bottom: calc(25px + 1em);
    }
    
    .chart__datasets {
      width: 70%;
      background: #f1c40f;
      color: white;
    }
      
    .chart__canvas {
      background: #2ecc71;
      width: 30%;
      aspect-ratio: 1;
    }
    
    @media (max-width: 600px) {
      .chart__body {
        flex-direction: column-reverse;
        align-items: normal;
        row-gap: 15px;
      }
      .chart__datasets {
        width: 100%;
        flex-grow: 1;
      }
      .chart__canvas {
        width: 100%;
        height: 50px;
      }
    }
    <div class="page">
    <div class="chart">
      <h3 class="chart__title"></h3>
      <div class="chart__body">
        <div class="chart__datasets">
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas tempor nunc mauris, sit amet placerat tortor lobortis dapibus. Nam lectus eros, maximus ac magna vel, congue consequat eros. Fusce id pretium diam. Cras sit amet pharetra ante. Sed quis commodo quam, vel facilisis ipsum. Vestibulum sodales iaculis arcu, et fringilla nisi ullamcorper sed. Donec interdum sit amet est non accumsan. Donec non augue feugiat, fermentum nunc non, convallis est. Cras vel ligula nec odio faucibus ultricies. Sed vulputate tortor eget pretium convallis. Cras interdum elit eget mi porta suscipit. Morbi ut velit diam. Etiam finibus eros et efficitur rutrum. Quisque viverra metus ac eleifend imperdiet. Quisque pretium ut purus vitae tempus. Duis varius risus congue velit faucibus, sed interdum purus consectetur.
        </div>
        <div class="chart__canvas">
        
        </div>
      </div>
    </div>
    </div>