Bored with all the vertical scrolls in websites? Today, let's build a simple horizontal scrolling page using CSS.
Overview
The key concept is to rotate the container 90 degrees and then rotate its child elements 90 degrees backwards to counter the container's rotation.
Here is a live demo of what we are going to build.
You can find the complete code here.
HTML
With that in mind, we can build it out really fast. Let's begin with HTML.
<div class="container">
<div>
<img src="./images/image1.jpeg" alt="" />
<p>image 1</p>
</div>
<div>
<img src="./images/image2.jpeg" alt="" />
<p>image 2</p>
</div>
<div>
<img src="./images/image3.jpeg" alt="" />
<p>image 3</p>
</div>
<div>
<img src="./images/image4.jpeg" alt="" />
<p>image 4</p>
</div>
<div>
<img src="./images/image5.jpeg" alt="" />
<p>image 5</p>
</div>
<div>
<img src="./images/image6.jpeg" alt="" />
<p>image 6</p>
</div>
<div>
<img src="./images/image7.jpeg" alt="" />
<p>image 7</p>
</div>
<div>
<img src="./images/image8.jpeg" alt="" />
<p>image 8</p>
</div>
</div>
CSS
CSS code is a bit more complicated but the concept has been covered above. We just need to code carefully and incremently.
Let's start with the big picture and give the page a structure.
.container {
/*
Width and height will swap after rotation.
To make the container as wide as the screen after rotation,
we need to set its initial height to 100vw.
*/
width: 500px;
height: 100vw;
}
.container div {
width: 100%;
height: 500px;
}
img {
width: 100%;
height: 100%;
object-fit: cover;
}
Now, the page should look like this. It's still far from what we want.
Let's rotate the container 90 degrees and its children 90 degrees backwards.
.container {
...
/*
translateY(-500px) makes the container align
to the left of the screen.
*/
transform: rotate(-90deg) translateY(-500px);
transform-origin: top right;
}
.container div {
...
transform: rotate(90deg);
}
Now it's closer to what we expect but it cannot scroll horizontally yet.
To make it horizontally scrollable is as easy as adding two lines of code.
.container {
...
overflow-x: hidden;
overflow-y: auto;
}
We are almost done except some clean-ups and polishing. Let's add the following code.
body {
margin: 0;
}
/*
To hide the scroll bar.
*/
::-webkit-scrollbar {
display: none;
}
* {
-ms-overflow-style: none;
scrollbar-width: none;
}
img {
...
}
.container div {
...
position: relative;
margin: 10px 0;
}
.container div:first-child {
margin: 0;
}
p {
padding: 10px;
background: white;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
The final page should look like this and scroll horizontally.
Here is the complete CSS code.
body {
margin: 0;
}
::-webkit-scrollbar {
display: none;
}
* {
-ms-overflow-style: none;
scrollbar-width: none;
}
img {
width: 100%;
height: 100%;
object-fit: cover;
}
.container {
width: 500px;
height: 100vw;
transform: rotate(-90deg) translateY(-500px);
transform-origin: top right;
overflow-x: hidden;
overflow-y: auto;
}
.container div {
position: relative;
width: 100%;
height: 500px;
transform: rotate(90deg);
margin: 10px 0;
}
.container div:first-child {
margin: 0;
}
p {
padding: 10px;
background: white;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
Notes
- In this example, we used squared child elements (500 * 500 images) and there is a reason for this. If the width:height ratio was not 1:1, we would have to work out how much to offset the child elements after rotation so that they do not overlap each other.
- For such cases and more advanced functionalities or effects, you would want to write some javacript code.
Top comments (1)
Thank you a lot. I wanted a div in my project to scroll horizontally, but I wanted the inputs for the scroll to be the ones you use to scroll vertically. This works perfectly. Also I didn't read these notes at the bottom so I struggled a lot, until I read them. Thanks! xD