Reputation: 39454
I am trying to create a responsive timeline that behaves as (https://codepen.io/anon/pen/KoGdqG):
For width higher than 600px is horizontal. The width of each section is responsive;
For width under than 600px becomes vertical;
So I have the following HTML:
<ul>
<li>
<span class="mark"></span>
<h3>Step 1</h3>
<p>Some text that describes text 1</p>
</li><li>
<span class="mark"></span>
<h3>Step 2</h3>
<p>Some text that describes text 2</p>
</li><li>
<span class="mark"></span>
<h3>Step 3</h3>
<p>Some text that describes text 3</p>
</li><li>
<span class="mark"></span>
<h3>Step 4</h3>
<p>Some text that describes text 4</p>
</li>
</ul>
And the following CSS:
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
body {
text-align: center;
}
ul {
max-width: 1000px;
padding: 0;
margin: 0 auto;
width: 60%;
list-style: none;
list-style: none;
list-style-type: none;
}
li {
padding: 20px;
margin: 0;
}
@media screen and (min-width: 600px) {
li {
display: inline-block;
width: 25%;
}
li span {
margin: 0 auto;
}
}
@media screen and (max-width: 599px) {
ul {
text-align: left;
}
li h3 {
margin-left: 40px;
}
li p {
margin-left: 40px;
}
}
li span {
background-color: white;
border: 2px solid green;
display: inline-block;
height: 24px;
width: 24px;
border-radius: 12px;
}
li h3 {
text-align: left;
}
li p {
text-align: left;
}
PROBLEM
The problem is how to create lines that connects each circle.
The lines become vertical with the vertical version of the timeline.
How can I do this?
Upvotes: 2
Views: 2626
Reputation: 10444
You can try adding a new element .line
inside each li
. The position of .line
is calculated according to width (percentage) and margin (pixels):
@media screen and (min-width: 600px) {
.line {
width: 100%;
height: 0;
border-top: solid 1px black;
position: relative;
display: block;
transform: translateX(calc(50% + 20px)) translateY(-18px);
}
li {
display: inline-block;
width: 25%;
}
li span {
margin: 0 auto;
}
}
@media screen and (max-width: 599px) {
.line {
width: 0;
height: 100%;
border-left: solid 1px black;
position: relative;
display: table-cell;
transform: translateX(-11px) translateY(calc(50% - 5px));
}
li {
display: table;
}
ul {
text-align: left;
}
li h3 {
margin-left: 40px;
}
li p {
margin-left: 40px;
}
}
li { display: table }
and `.line { display: table-cell } is a workaround to make the inner element aware of the height of the parent element. The height is calculated dynamically according to the text content, so we must use this or flexbox.
Here is a working snippet:
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
body {
text-align: center;
}
ul {
max-width: 1000px;
padding: 0;
margin: 0 auto;
width: 60%;
list-style: none;
list-style: none;
list-style-type: none;
}
li {
padding: 20px;
margin: 0;
}
@media screen and (min-width: 600px) {
.line {
width: 100%;
height: 0;
border-top: solid 1px black;
position: relative;
display: block;
transform: translateX(calc(50% + 20px)) translateY(-18px);
}
li {
display: inline-block;
width: 25%;
}
li span {
margin: 0 auto;
}
}
@media screen and (max-width: 599px) {
li {
display: table;
}
.line {
width: 0;
height: 100%;
border-left: solid 1px black;
position: relative;
display: table-cell;
transform: translateX(-11px) translateY(calc(50% - 5px));
}
ul {
text-align: left;
}
li h3 {
margin-left: 40px;
}
li p {
margin-left: 40px;
}
}
li span {
background-color: white;
border: 2px solid green;
display: inline-block;
height: 24px;
width: 24px;
border-radius: 12px;
}
li h3 {
text-align: left;
}
li p {
text-align: left;
}
<ul>
<li>
<span class="mark"></span>
<div class="line"></div>
<h3>Step 1</h3>
<p>Some text that describes text 1</p>
</li><li>
<span class="mark"></span>
<div class="line"></div>
<h3>Step 2</h3>
<p>Some text that describes text 2</p>
</li><li>
<span class="mark"></span>
<div class="line"></div>
<h3>Step 3</h3>
<p>Some text that describes text 3</p>
</li><li>
<span class="mark"></span>
<h3>Step 4</h3>
<p>Some text that describes text 4</p>
</li>
</ul>
Upvotes: 0
Reputation: 4147
Another way to make this work is using pseudo classes as well. Add a div before the ul:
<div class="line"></div>
<ul>...</ul>
https://codepen.io/anon/pen/jzeqEM
Add these classes:
@media screen and (min-width: 600px) {
.line{
width: 45%;
margin: 0px auto;
height: 3px;
background: black;
display: block;
position: relative;
z-index: 1;
top: 33px;
}
}
@media screen and (max-width: 599px) {
li span::after{
content: "";
width: 3px;
margin: 0px auto;
height: 140px;
background: black;
display: block;
position: relative;
z-index: 1;
top: 20px;
}
li:nth-child(4) span::after{
content: "";
background: none;
}
}
Upvotes: 1
Reputation: 3572
A solution (CSS only) is to connect each circle by adding borders to the list elements depending on the viewport width and repositioning the circle:
/* vertical connections */
@media screen and (max-width: 599px) {
li {
border-width: 0 0 0 1px !important; /* change visible border to left */
margin-top: 0 !important;
}
li span.mark {
left: -12px; /* half circle height */
}
}
/* for horizontal connections */
li {
position: relative;
border-style: solid;
border-width: 1px 0 0 0; /* show top border */
margin-top: 15px;
}
li span.mark {
position: absolute;
top: -12px; /* half circle height */
}
Your complete CSS (I've reorganized a bit) could look like this:
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box
}
body {
text-align: center
}
li {
margin: 0;
padding: 20px
}
ul {
list-style: none;
list-style: none;
list-style-type: none;
margin: 0 auto;
max-width: 1000px;
padding: 0;
width: 60%
}
@media screen and (min-width: 600px) {
li {
display: inline-block;
width: 25%
}
li span {
margin: 0 auto
}
}
@media screen and (max-width: 599px) {
li {
border-width: 0 0 0 1px !important;
margin-left: 15px;
margin-top: 0 !important
}
li h3 {
margin-left: 40px
}
li p {
margin-left: 40px
}
li span.mark {
left: -12px
}
ul {
text-align: left
}
}
li {
border-style: solid;
border-width: 1px 0 0;
margin-top: 15px;
position: relative
}
li h3 {
text-align: left
}
li p {
text-align: left
}
li span {
background-color: #fff;
border: 2px solid green;
border-radius: 12px;
display: inline-block;
height: 24px;
width: 24px
}
li span.mark {
position: absolute;
top: -12px
}
NOTE: Tested only in codepen!
Upvotes: 1