I'm trying to build a stepping wizard form layout with a bar at the top of the page containing a dynamic number of steps (nodes) and progress bars connecting the nodes. I'm having trouble getting the progress bars and nodes to cooperate.
The idea is to have each nodes spaced evenly on the page horizontally (already working nicely using flexbox), and the progress bars fluidly filling the gaps between the nodes.
I am currently trying to use an <li> to contain each iteration of the progress bar & <a> pairs, but it is not laying out like I need it to (the progress bars are not behaving fluidly and not filling empty space between the <a> tags).
Is this the best way to lay this out?
Just though I'd confirm this is the best way to lay these out before going any further.
EDIT 1 (Clarifying goal):
This image is an example of what I am trying to achieve.
The progress bar and red <a> node are both within the same <li>. I have given the progress bar a width of 90% for this example but the goal is to only assign a width to the red <a> node and have the project bar fluidly fill the remaining space.
Below is the HTML & SCSS I am currently using:
<div class="panel panel-default">
<div class="panel-heading">
<div class="panel-title">Project Milestones</div>
</div>
<div class="panel-body">
<ul class="milestone-bar">
<li>
<div class="progress project-progress">
<div class="progress-bar" role="progressbar" aria-valuenow="100.0" aria-valuemin="0" aria-valuemax="100" style="width: 100.0%;">
100%
</div>
</div>
Milestone 1
</li>
<li>
<div class="progress project-progress">
<div class="progress-bar" role="progressbar" aria-valuenow="100.0" aria-valuemin="0" aria-valuemax="100" style="width: 100.0%;">
100%
</div>
</div>
Milestone 3
</li>
<li>
<div class="progress project-progress">
<div class="progress-bar" role="progressbar" aria-valuenow="50.0" aria-valuemin="0" aria-valuemax="100" style="width: 50.0%;">
50%
</div>
</div>
Milestone 2
</li>
</ul>
</div>
</div>
ul.milestone-bar {
padding: 0;
margin: 0 0 15px 0;
display: flex;
li {
width: 100%;
list-style: none;
display: inline-block;;
a {
width: 30px;
height: 30px;
font-size: 12px;
border-radius: 15px;
background-color: red;
float:right;
&:hover {
background: none;
border: 4px solid blue;
}
&:active {
background-color: darkblue;
}
&:focus {
background-color: green;
}
}
.project-progress {
background-color: #d3d3d3;
display: inline-block;
margin: 0;
}
}
}
Is this on the right track?
Below is a snippet of the above:
ul.milestone-bar {
padding: 0;
margin: 0 0 15px 0;
display: flex;
}
ul.milestone-bar li {
width: 100%;
list-style: none;
display: inline-block;
}
ul.milestone-bar li a {
width: 30px;
height: 30px;
font-size: 12px;
border-radius: 15px;
background-color: red;
float: right;
}
ul.milestone-bar li a:hover {
background: none;
border: 4px solid blue;
}
ul.milestone-bar li a:active {
background-color: darkblue;
}
ul.milestone-bar li a:focus {
background-color: green;
}
ul.milestone-bar li .project-progress {
background-color: #d3d3d3;
display: inline-block;
margin: 0;
}
<div class="panel panel-default">
<div class="panel-heading">
<div class="panel-title">Project Milestones</div>
</div>
<div class="panel-body">
<ul class="milestone-bar">
<li>
<div class="progress project-progress">
<div class="progress-bar" role="progressbar" aria-valuenow="100.0" aria-valuemin="0" aria-valuemax="100" style="width: 100.0%;">
100%
</div>
</div>
Milestone 1
</li>
<li>
<div class="progress project-progress">
<div class="progress-bar" role="progressbar" aria-valuenow="100.0" aria-valuemin="0" aria-valuemax="100" style="width: 100.0%;">
100%
</div>
</div>
Milestone 3
</li>
<li>
<div class="progress project-progress">
<div class="progress-bar" role="progressbar" aria-valuenow="50.0" aria-valuemin="0" aria-valuemax="100" style="width: 50.0%;">
50%
</div>
</div>
Milestone 2
</li>
</ul>
</div>
</div>
So I did some changes to your code:
Added flex to each li to create nested flex children here:
ul.milestone-bar li {
width: 100%;
list-style: none;
display: flex;
}
Added flex: 1 for it to flex to the whole width and vertically align it to the center using align-self: center to your project-progress like this:
ul.milestone-bar li .project-progress {
background-color: #d3d3d3;
display: inline-block;
margin: 0;
flex: 1;
align-self: center
}
Added the progress bar style:
ul.milestone-bar li .project-progress .progress-bar {
background: #0095FF;
text-align: center;
}
Also adjusted the milestone-bar to look better:
ul.milestone-bar li a {
width: 60px;
height: 60px;
font-size: 10px;
border-radius: 50%;
background-color: red;
text-align: center;
line-height: 60px;
}
ul.milestone-bar li a:hover {
background: none;
border: 4px solid blue;
line-height: 52px;
}
To top it up, used box-sizing: border-box to all elements in the page for better management of border especially to remove the 'jumps' when you hover.
* {
box-sizing: border-box;
}
ul.milestone-bar {
padding: 0;
margin: 0 0 15px 0;
display: flex;
}
ul.milestone-bar li {
width: 100%;
list-style: none;
display: flex;
}
ul.milestone-bar li a {
width: 60px;
height: 60px;
font-size: 10px;
border-radius: 50%;
background-color: red;
text-align: center;
line-height: 60px;
}
ul.milestone-bar li a:hover {
background: none;
border: 4px solid blue;
line-height: 52px;
}
ul.milestone-bar li a:active {
background-color: darkblue;
}
ul.milestone-bar li a:focus {
background-color: green;
}
ul.milestone-bar li .project-progress {
background-color: #d3d3d3;
display: inline-block;
margin: 0;
flex: 1;
align-self: center
}
ul.milestone-bar li .project-progress .progress-bar {
background: #0095FF;
text-align: center;
}
<div class="panel panel-default">
<div class="panel-heading">
<div class="panel-title">Project Milestones</div>
</div>
<div class="panel-body">
<ul class="milestone-bar">
<li>
<div class="progress project-progress">
<div class="progress-bar" role="progressbar" aria-valuenow="100.0" aria-valuemin="0" aria-valuemax="100" style="width: 100.0%;">
100%
</div>
</div>
Milestone 1
</li>
<li>
<div class="progress project-progress">
<div class="progress-bar" role="progressbar" aria-valuenow="100.0" aria-valuemin="0" aria-valuemax="100" style="width: 100.0%;">
100%
</div>
</div>
Milestone 3
</li>
<li>
<div class="progress project-progress">
<div class="progress-bar" role="progressbar" aria-valuenow="50.0" aria-valuemin="0" aria-valuemax="100" style="width: 50.0%;">
50%
</div>
</div>
Milestone 2
</li>
</ul>
</div>
</div>
Let me know your feedback on this. Thanks!
Related
I just started to FE after a couple of years in BE.
Developing an analytics card with using Angular on FE and .net Core on BE.
Stucked on a point to find out the best practice about to change background-color: property of a class beneath of main class.
<div class="row">
<div class="journey-card-bottom">
<div *ngFor="let bottom of top.breakDown | keyvalue: originalOrder">
<div>
<span>{{bottom.key}}</span>
</div>
<div class="row">
<div class="col-lg-10">
<div class="progress">
<div class="progress-bar" role="progressbar"
[ngStyle]="{'width': bottom.value > 0 ? bottom.value + '%' : '8px'}"></div>
<span class="percentage-value">{{bottom.value}}</span>
</div>
</div>
</div>
</div>
</div>
</div>
Screenshot to the desired outcome
In my CSS;
.journey-card-bottom {
border: 1px solid #DADCDD;
box-sizing: border-box;
padding: 10px;
line-height: 3;
width: 100%;
height: 435px;
}
.progress {
background-color: white !important;
margin-top: 5px;
}
.progress-bar {
border-radius: 0.25rem;
height: 8px;
align-self: center;
background-color: #0B4886;
}
.journey-card-bottom .progress-bar:nth-of-type(1) {
background-color: #68D391;
}
.journey-card-bottom .progress-bar:nth-of-type(2) {
background-color: #FCAF65;
}
It seems :nth-of-type(1) changes the background color but not only for 1st bar, for all of them.
:nth-of-type(2)does not effect at all i guess because there is no direct parent-child relation between each other.
On the other hand i know i can achieve with using [ngStyle] based on the item index in [ngFor] however i'm not sure if it's the best practice or not.
:nth-of-type() applies to sibling elements. Since .progress-bar is the first sibling within .progress and has no other siblings with the class .progress-bar, only the styles declared in .journey-card-bottom .progress-bar:nth-of-type(1) will be applied. Here is a code snippet showing your CSS working by changing the HTML structure:
.journey-card-bottom {
border: 1px solid #DADCDD;
box-sizing: border-box;
padding: 10px;
line-height: 3;
width: 100%;
height: 435px;
}
.progress {
background-color: white !important;
margin-top: 5px;
}
.progress-bar {
border-radius: 0.25rem;
height: 8px;
align-self: center;
background-color: #0B4886;
}
.journey-card-bottom .progress-bar:nth-of-type(1) {
background-color: #68D391;
}
.journey-card-bottom .progress-bar:nth-of-type(2) {
background-color: #FCAF65;
}
<div class="journey-card-bottom">
<div class="progress">
<div class="progress-bar" role="progressbar"></div>
<span class="percentage-value">90</span>
<div class="progress-bar" role="progressbar"></div>
<span class="percentage-value">60</span>
</div>
</div>
To solve your issue, I would suggest using :nth-of-type() on the top-level element of the for loop. In the below example, the top-level element has the class .target-class:
.journey-card-bottom {
border: 1px solid #DADCDD;
box-sizing: border-box;
padding: 10px;
line-height: 3;
width: 100%;
height: 435px;
}
.progress {
background-color: white !important;
margin-top: 5px;
}
.progress-bar {
border-radius: 0.25rem;
height: 8px;
align-self: center;
background-color: #0B4886;
}
.target-class:nth-of-type(1) .progress-bar {
background-color: #68D391;
}
.target-class:nth-of-type(2) .progress-bar {
background-color: #FCAF65;
}
<!-- Rendered HTML from the component -->
<div class="row">
<div class="journey-card-bottom">
<div class="target-class">
<div>
<span>Passed</span>
</div>
<div class="row">
<div class="col-lg-10">
<div class="progress">
<div class="progress-bar" role="progressbar"></div>
<span class="percentage-value">90</span>
</div>
</div>
</div>
</div>
<div class="target-class">
<div>
<span>Referred</span>
</div>
<div class="row">
<div class="col-lg-10">
<div class="progress">
<div class="progress-bar" role="progressbar"></div>
<span class="percentage-value">60</span>
</div>
</div>
</div>
</div>
</div>
</div>
I currently have an event tracker made using html and css. My issue is that I would like to get ride of display: flex; due to browser-compatibility issues. Is there an alternative to achieve the same result? I tried using display:inline-block because without flex all steps were coming in different lines.
HTML:
<div class="container">
<div class="row event">
<div class="col-xs-3 event-step">
<p class="event-stepnum">Step 1</p>
<div class="progress">
<div class="progress-bar"></div>
</div>
</div>
<div class="col-xs-3 event-step complete">
<p class="event-stepnum">Step 2</p>
<div class="progress">
<div class="progress-bar"></div>
</div>
</div>
<div class="col-xs-3 event-step">
<p class="event-stepnum">Step 3</p>
<div class="progress">
<div class="progress-bar"></div>
</div>
</div>
</div>
</div>
CSS:
.event > .event-step {
padding: 0;
position: relative;
}
.event > .event-step .event-stepnum {
color: #595959;
font-size: 16px;
margin-bottom: 5px;
}
.steps .step-on,
.steps .step-done {
background-color: #1b7e28;
color: #1b7e28;
border: 1px solid transparent;
}
.progress {
position: relative;
border-radius: 0px;
height: 5px;
box-shadow: none;
margin: 20px 0;
}
.progress > .progress-bar {
width: 0px;
box-shadow: none;
background: #fbe8aa;
}
.event-step.complete > .progress > .progress-bar {
width: 100%;
}
.row {
display:flex;
}
JSFiddle Demo
Just replace the display:flex by display:inline-block and give your step divs a fixed width:
.event > .event-step {
padding: 0;
position: relative;
width: 200px;
}
.row {
display: inline-block;
}
https://jsfiddle.net/onk2cqhg/
I have started to create bootstrap progress bar with custom colors etc. however there appears grey border above progress bar and I am unable to understand where this border comes from and how to remove it.
CSS:
.progress-info {
color: #ffffff;
}
.progress-info {
padding-top: 34px;
background-color: #005861;
}
.progress {
background-color: #F3723F;
border: 5px solid #F3723F;
border-radius: 4px;
height: 18px;
}
.progress-second {
background-color: #45BDA1;
border: 5px solid #45BDA1;
}
Html:
<div class="progress-info" data-bind="with: $data.statistics">
<div class="row">
<div class="col-md-4">Your score</div>
<div class="progress col-md-6">
<div class="progress-bar progress-bar-score" role="progressbar" aria-valuemin="0" aria-valuemax="100" data-bind="style: {width: $data.score}" style="width: 6%;"></div>
</div>
<div class="col-md-2" data-bind="text: $data.score">6%</div>
</div>
<div class="row">
<div class="col-md-4">Progress</div>
<div class="progress progress-second col-md-6">
<div class="progress-bar progress-bar-progress" role="progressbar" aria-valuemin="0" aria-valuemax="100" data-bind="style: {width: $data.score}" style="width: 6%;"></div>
</div>
<div class="col-md-2"><span data-bind="text: $data.success_cnt">2</span> / <span data-bind="text: $data.attempts">35</span>
</div>
</div>
</div>
JsFiddle
That is not a border. It is a box-shadow. You only need to give box-shadow: none; to the .progress.
Jsfiddle
.progress {
height: 20px;
margin-bottom: 20px;
overflow: hidden;
background-color: #f5f5f5;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1);
box-shadow: none;
}
I have a group of stats styled as shown below, but if I want to center the group, it will use the width of the descriptions that extend past and have a larger width. What's the easiest way to center according to the width of just the stat numbers and still have the descriptions below them?
.container {
text-align: center;
}
.stats {
display: block;
margin: 0 auto 30px auto;
}
.left-stats {
text-align: right;
display: inline-block;
margin-right: 40px;
}
.left-stats .single-stat {
text-align: right;
}
.right-stats {
display: inline-block;
}
.right-stats .single-stat {
text-align: left;
}
.single-stat {
margin-bottom: 20px;
}
.number {
font: 60px"Bebas Neue";
font-weight: bold;
margin-bottom: -5px;
}
<div class="container">
<h3>Header</h3>
<div class="stats">
<div class="left-stats">
<div class="single-stat">
<div class="number">1,200</div>
<div class="desc">Staff on campus supported</div>
</div>
<div class="single-stat">
<div class="number">10</div>
<div class="desc">Departments reached</div>
</div>
</div>
<div class="right-stats">
<div class="single-stat">
<div class="number">06</div>
<div class="desc">Different home states/countries</div>
</div>
<div class="single-stat">
<div class="number">10</div>
<div class="desc">People who love food and technology</div>
</div>
</div>
</div>
</div>
I have a solution using your HTML and using display: table-cell instead of display: inline-block. Instead of a 40px margin to create the space between the columns, I added 20px left/right padding in the relevant elements.
Note that I added dotted blue borders for demonstration purposes, you can remove them.
.container {
text-align: center;
}
.stats {
display: table;
width: 100%;
margin: 0 auto 30px auto;
border: 1px dotted blue;
}
.left-stats {
text-align: right;
display: table-cell;
width: 50%;
padding-right: 20px;
border: 1px dotted blue;
}
.left-stats .single-stat {
text-align: right;
}
.right-stats {
display: table-cell;
width: 50%;
padding-left: 20px;
border: 1px dotted blue;
}
.right-stats .single-stat {
text-align: left;
}
.single-stat {
margin-bottom: 20px;
}
.number {
font: 60px"Bebas Neue";
font-weight: bold;
margin-bottom: -5px;
}
<div class="container">
<h3>Header</h3>
<div class="stats">
<div class="left-stats">
<div class="single-stat">
<div class="number">1,200</div>
<div class="desc">Staff on campus supported</div>
</div>
<div class="single-stat">
<div class="number">10</div>
<div class="desc">Departments reached</div>
</div>
</div>
<div class="right-stats">
<div class="single-stat">
<div class="number">06</div>
<div class="desc">Different home states/countries</div>
</div>
<div class="single-stat">
<div class="number">10</div>
<div class="desc">People who love food and technology</div>
</div>
</div>
</div>
</div>
You mean something like this?
.number {
font: 60px"Bebas Neue";
font-weight: bold;
margin-bottom: -5px;
text-align: center;
}
I have a HTML structure with given CSS.
Both caption and progress elements should be rendered in same line. caption elements should not have fixed width and progress elements should fill up the rest of the space next to caption based on their inline-set width, which means that every progress element will have a different total pixel-width but should fill up only the given percentage of available space.
HTML structure and CSS rules can be changed in any way.
Is it possible to solve this problem with CSS only?
.table {
padding: 15px;
width: 280px;
border: 1px solid black;
font-family: sans-serif;
font-size: 12px;
}
.caption {
float: left;
}
.progress {
height: 14px;
border: 1px solid white;
border-radius: 4px;
background-color: green;
overflow: hidden;
}
.value {
margin-left: 5px;
}
<div class="table">
<div class="row">
<div class="caption">Short text: </div>
<div class="progress" style="width:11.65%">
<span class="value">11.65</span>
</div>
</div>
<div class="row">
<div class="caption">A bit longer text: </div>
<div class="progress" style="width:100%">
<span class="value">100.00</span>
</div>
</div>
<div class="row">
<div class="caption">X: </div>
<div class="progress" style="width:45.50%">
<span class="value">45.50</span>
</div>
</div>
</div>
Have you considered using Flexbox?
Just add this rule:
.row {
display: flex;
}
If your are concerned about browser support, an alternative would be using display:table. You should change your markup and CSS, like this:
.table {
border: 1px solid black;
font-family: sans-serif;
font-size: 12px;
padding: 15px;
width: 280px;
}
.inner-table {
display: table;
}
.row {
display: table-row;
}
.caption {
display: table-cell;
white-space: nowrap;
width: 1%;
}
.progress {
background-color: green;
border: 1px solid white;
border-radius: 4px;
display: table-cell;
height: 14px;
}
.value {
margin-left: 5px;
display:block;
width:0;
overflow: visible;
}
<div class="table">
<div class="inner-table">
<div class="row">
<div class="caption">Short text: </div>
<div style="width:1.65%" class="progress">
<span class="value">1.65</span>
</div>
<div class="remainder"></div>
</div>
</div>
<div class="inner-table">
<div class="row">
<div class="caption">A bit longer text: </div>
<div style="width:100%" class="progress">
<span class="value">100.00</span>
</div>
<div class="remainder"></div>
</div>
</div>
<div class="inner-table">
<div class="row">
<div class="caption">X: </div>
<div class="progress" style="width:45.50%">
<span class="value">45.50</span>
</div>
<div class="remainder"></div>
</div>
</div>
</div>
Please try this - padding-right: 5px; display:inline; add these properties in progress class and also remove width in progress.
Well, just for the future reference, I was playing a bit with the flexbox thingie and came up with this:
.table {
padding: 15px;
width: 280px;
border: 1px solid black;
font-family: sans-serif;
font-size: 12px;
}
.row {
display: flex;
}
.caption {
margin: 1px 5px 1px 0;
}
.progress {
flex-grow: 1;
margin: auto;
}
.progress-content {
height: 14px;
border-radius: 4px;
background-color: green;
}
.value {
margin-left: 5px;
}
<div class="table">
<div class="row">
<div class="caption">Short text:</div>
<div class="progress">
<div class="progress-content" style="width:11.65%">
<span class="value">11.65</span>
</div>
</div>
</div>
<div class="row">
<div class="caption">A bit longer text:</div>
<div class="progress">
<div class="progress-content" style="width:100%">
<span class="value">100.00</span>
</div>
</div>
</div>
<div class="row">
<div class="caption">X:</div>
<div class="progress">
<div class="progress-content" style="width:45.50%">
<span class="value">45.50</span>
</div>
</div>
</div>
</div>
If I get a solution without flexbox, will accept it as an answer :)