How to make a flex-container's elements overflow to the left?

Viewed 117

In the middle (not banner or footer) section of my page, I have two elements: classed as left-container and right-container.

I want to fill the left-container with many columns of a specific width, and have them overflow to the left, such that the page loads to show their right-most element and the user must scroll left to see the others.

How is this possible with flexbox?

Here's my code:

@import url("https://fonts.googleapis.com/css2?family=Heebo:wght@600&display=swap");

body {
  margin: 0;
  padding: 0;
}

.page-container {
  display: flex;
  flex-direction: column;
  height: 100vh;
  background-color: teal;
  align-items: stretch;
  flex-direction: column;
}

.banner {
  background-color: lightcyan;
  position: relative;
  width: 100%;
  height: 80px;
}

.banner-title {
  font-family: "Heebo";
  font-weight: 600;
  font-size: 40px;
  padding: 10px;
}

.footer {
  width: 100%;
  background-color: thistle;
  height: 30px;
}

.body-container {
  background-color: lightcyan;
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: flex-end;
}

.left-container {
  background-color: greenyellow;
  width: 100vw;
  display: flex;
  justify-content: flex-end;
  flex-wrap: nowrap;
  overflow: auto;
}

.right-container {
  background-color: tomato;
  width: 350px;
  height: 100%;
}

.column-container {
  background-color: red;
  width: 150px;
  margin: 5px;
  display: flex;
  flex-direction: column;
}
<!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="styles.css" />
  </head>
  <body>
    <div class="page-container">
      <div class="banner">
        <div class="banner-title">Title</div>
      </div>
      <div class="body-container">
        <div class="left-container">
          <div class="column-container"></div>
          <div class="column-container"></div>
          <div class="column-container"></div>
          <div class="column-container"></div>
          <div class="column-container"></div>
          <div class="column-container"></div>
          <div class="column-container"></div>
          <div class="column-container"></div>
        </div>
        <div class="right-container"></div>
      </div>
      <div class="footer">Footer</div>
    </div>
    <script src="./stopwatch.js"></script>
  </body>
</html>

Images of desired result: enter image description here

2 Answers

As unusual an experience as it is likely to cause, you can use a mixture of the flex-direction and order properties to have a scrollable container start on its right-most side.

Like was mentioned in the comments, you will need a container around your columns with flex-direction: row-reverse; to start scrolling from the right. This will place your columns in the opposite order you expect, however.

If you try and use the direction: ltr; style to fix this issue, the scrollbar will again start from the left. Instead, you must set the order property of your columns in reverse. This will take some javascript or server-side templating if you want to avoid unnecessary nth-child selectors.

Here's an example.

.column {
  display: flex;
  flex-direction: column;
}

.row {
  display: flex;
  flex-direction: row;
}

#main {
  flex-direction: row-reverse;
}

#left {
  flex-direction: row-reverse;
  overflow-x: scroll;
}


#banner { background-color: lightblue; }
#right { background-color: salmon; width: 400px; }
#left { background-color: teal; }
#footer { background-color: purple; }
<div class="column">
  <div class="row" id="banner">Banner</div>
  <div class="row" id="main">
    <div id="right">Right Container</div>
    <div class="row" id="left">
      <div class="column" style="order:12">Column Container 1</div>
      <div class="column" style="order:11">Column Container 2</div>
      <div class="column" style="order:10">Column Container 3</div>
      <div class="column" style="order:9">Column Container 4</div>
      <div class="column" style="order:8">Column Container 5</div>
      <div class="column" style="order:7">Column Container 6</div>
      <div class="column" style="order:6">Column Container 7</div>
      <div class="column" style="order:5">Column Container 8</div>
      <div class="column" style="order:4">Column Container 9</div>
      <div class="column" style="order:3">Column Container 10</div>
      <div class="column" style="order:2">Column Container 11</div>
      <div class="column" style="order:1">Column Container 12</div>
    </div>
  </div>
  <div class="row" id="footer">Footer</div>
</div>

It is not possible to do that with CSS because CSS is made in such a unique way that you can do the things in right manner without any bugs in code .

What you are saying is a behavior opposite to what CSS made for ( which violates its basic rule ) .

Instead you can show the data which user should see first on the left and then he/she can scroll for more on the right side ( This is your best and easy shot) . It will remove other headache like which comes first and last and changing order.

Else you can use JS function to make it possible in opposite way

@import url("https://fonts.googleapis.com/css2?family=Heebo:wght@600&display=swap");
body {
  margin: 0;
  padding: 0;
}

.page-container {
  display: flex;
  flex-direction: column;
  height: 100vh;
  background-color: teal;
  align-items: stretch;
  flex-direction: column;
}

.banner {
  background-color: lightcyan;
  position: relative;
  width: 100%;
  height: 80px;
}

.banner-title {
  font-family: "Heebo";
  font-weight: 600;
  font-size: 40px;
  padding: 10px;
}

.footer {
  width: 100%;
  background-color: thistle;
  height: 30px;
}

.body-container {
  background-color: lightcyan;
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: flex-end;
}

.left-container {
  background-color: greenyellow;
  width: 300px;
  display: flex;
  overflow: auto;
}

.right-container {
  background-color: tomato;
  width: 350px;
  height: 100%;
}

.column-container {
  background-color: red;
  width: 150px;
  margin: 5px;
  padding: 40px;
  flex-direction: row-reverse;
  direction: rtl
}
<!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="styles.css" />
</head>

<body>
  <div class="page-container">
    <div class="banner">
      <div class="banner-title">Title</div>
    </div>
    <div class="body-container">
      <div class="left-container">
        <div class="column-container"></div>
        <div class="column-container"></div>
        <div class="column-container"></div>
        <div class="column-container"></div>
        <div class="column-container"></div>
        <div class="column-container"></div>
        <div class="column-container"></div>
        <div class="column-container"></div>
      </div>
      <div class="right-container"></div>
    </div>
    <div class="footer">Footer</div>
  </div>
  <script src="./stopwatch.js"></script>
</body>

</html>

Using order is the property to change the order of elements without changing position

Related