2

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

GucciBananaKing99
  • 1,473
  • 1
  • 11
  • 31
  • 1
    Your current sample code doesn't produce anything near the desired result. Despite the widths you have specified, the elements shrink, because you did not disable that flexbox feature yet. And once you do, you'd probably need to stick your left column into an additional wrapper element, and give that one the scroll bar. Getting the scrollbar to "start" on the opposite site, I don't think that is a thing flexbox can do itself; if anything, you'd probably need a combination of different `direction` values, `rtl` on the outside, and reversed again for the inner element, something like that. – CBroe Aug 25 '21 at 14:35
  • 1
    `dir="rtl"` + `flex-direction: row-reverse` – tacoshy Aug 25 '21 at 14:39
  • [Generate scroll bar for overflow to the left](https://stackoverflow.com/q/38698797/3597276) – Michael Benjamin Aug 26 '21 at 12:28

2 Answers2

1

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>
D M
  • 5,769
  • 4
  • 12
  • 27
-1

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