Center text over a flex element - css

I am trying to build a custom stepper with CSS and I am hitting a wall to center the label on top of each step.
I've build a quick and simplified version of my current implementation :
.wrapper {
display: flex;
}
.circle-wrapper {
flex: 1;
}
.circle-wrapper.active>.circle {
background-color: #3490DC;
transform: scaleX(1.2) scaleY(1.2)
}
.circle-wrapper.complete>.circle {
background-color: #38C172;
}
.circle {
width: 34px;
height: 34px;
background-color: #B8C2CC;
border-radius: 100%;
}
.label {
margin-bottom: 10px;
}
.wrapper> :last-child {
flex: none;
}
.line {
height: 4px;
width: 100%;
background-color: #1F9D55;
position: relative;
bottom: 19px;
}
<div class="wrapper">
<div class="circle-wrapper complete">
<div class="label">Label 1</div>
<div class="circle"></div>
<div class="line"></div>
</div>
<div class="circle-wrapper active">
<div class="label">Label 2 with a longer name</div>
<div class="circle"></div>
<div class="line"></div>
</div>
<div class="circle-wrapper">
<div class="label">Label 3</div>
<div class="circle"></div>
<div class="line"></div>
</div>
<div class="circle-wrapper">
<div class="label">Label 4</div>
<div class="circle"></div>
</div>
</div>
You can see it here in this codepen
So far so good, but I want to center the label over the circle div without impacting the flex size between each circle and I can't manage to do it.
Any advice ?

You can use a left and a transform to move it into the centre:
.wrapper {
display: flex;
}
.circle-wrapper {
flex: 1;
position:relative;
}
.circle-wrapper.active>.circle {
background-color: #3490DC;
transform: scaleX(1.2) scaleY(1.2)
}
.circle-wrapper.complete>.circle {
background-color: #38C172;
}
.circle {
width: 34px;
height: 34px;
background-color: #B8C2CC;
border-radius: 100%;
}
.label {
position:relative;
left: 17px; /* move left 17px (half of circle width) */
margin-bottom: 10px;
transform: translateX(-50%); /* move it backwards 50% of itself */
text-align: center; /* align text in centre */
}
.wrapper> :last-child {
flex: none;
}
.line {
height: 4px;
width: 100%;
background-color: #1F9D55;
position: relative;
bottom: 19px;
}
<div class="wrapper">
<div class="circle-wrapper complete">
<div class="label">Label 1</div>
<div class="circle"></div>
<div class="line"></div>
</div>
<div class="circle-wrapper active">
<div class="label">Label 2 with a longer name</div>
<div class="circle"></div>
<div class="line"></div>
</div>
<div class="circle-wrapper">
<div class="label">Label 3</div>
<div class="circle"></div>
<div class="line"></div>
</div>
<div class="circle-wrapper">
<div class="label">Label 4</div>
<div class="circle"></div>
</div>
</div>

If you want to center it always above the circle, I would use the following: put the label inside the circle and use the following CSS properties:
.circle {
position: relative;
width: 34px;
height: 34px;
background-color: #B8C2CC;
border-radius: 100%;
margin: 50px 100px; /* remove this */
}
.circle .label {
position: absolute;
left: 50%;
bottom: 100%;
transform: translateX(-50%);
white-space: nowrap;
}
<div class="circle">
<div class="label">Small One</div>
</div>
<div class="circle">
<div class="label">Very long label with long text</div>
</div>
The percentage values of left and bottom reference to the width of the parent element and the percentage value of transform: translate references to the element's size. This allows you to position it in the center of the parent with left: 50% and then moving it to the left again by the half of the width of the element itself.

Related

How do I get rid of this extra space below this column when using bootstrap 5?

I made the changes as you described but when I check to see how it would look on the phone the blue box and the pink box are separated which I want to be together. I have attached a screenshot of how it looks and I want it to look similar to the desktop version.
I am not sure which entity might be causing this issue.
--EDIT--
Just to provide more clarity here is a screenshot of how the container_tag and container_box should look in the mobile screen (365px).
Should look like this
Is looking like this
.side_feedback{
background-color: pink;
padding: 10px;
height: 300px;
width: 180px;
border-radius: 10%;
margin-left: 17px;
}
.container_tag{
background-color: royalblue;
min-height: 200px;
max-width: 2rem;
border: 6px solid royalblue;
float: left;
}
.tag{
transform: rotate(-90deg);
position: relative;
top: 8rem;
}
.container_box{
background-color: pink;
min-height: 200px;
border-left: 6px solid white;
width: 95%;
position: relative;
float: left;
}
<div class="container-fluid">
<div class="row mb-4 g-5">
<div class="order-2 order-sm-1 col-lg-2 col-md-2 col-xs-10">
<div class="col-md">
<div class="side_feedback">
<p>Give us feedback!</p>
</div>
</div>
</div>
<div class="order-1 order-sm-2 col-10">
<div class="row row-cols-1 row-cols-sm-1 row-cols-md-1 row-cols-lg-1 row-cols-auto g-4">
<div class="col-12">
<div class="container_tag">
<h3 class="tag">TEXT</h3>
</div>
<div class="container_box">
</div>
</div>
<div class="col-12">
<div class="container_tag">
<h3 class="tag">TEXT</h3>
</div>
<div class="container_box">
</div>
</div>
<div class="col-12">
<div class="container_tag">
<h3 class="tag">TEXT</h3>
</div>
<div class="container_box">
</div>
</div>
</div>
</div>
</div>
If you’re referencing the large vertical white space below the two pink blocks, that’s there because you’re using position: relative on the pink container_box. position: relative positions the element normally (below your container_tag div) and then moves the element to the new position — the original space remains.
To get rid of the white space, add float: left to the styles for both of your containers.
.container_tag {
background-color: royalblue;
min-height: 180px;
width: 9%;
max-width: 3.2rem;
float: left;
position: relative;
}
.tag {
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%) rotate(-90deg)
}
.container_box {
background-color: pink;
min-height: 180px;
border-left: 6px solid white;
width: 91%;
position: relative;
float: left;
}
#media (min-width:768px) {
.container_box {
width: calc(100% - 3.2rem);
}
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-12 col-sm-10 px-0">
<div class="row gx-0">
<div class="col-12 mb-3">
<div class="container_tag">
<h3 class="tag">Text</h3>
</div>
<div class="container_box">
</div>
</div>
<div class="col-12 mb-3">
<div class="container_tag">
<h3 class="tag">Text</h3>
</div>
<div class="container_box">
</div>
</div>
</div>
</div>
</div>
</div>
One other note - you don't need to give the same column class for different breakpoints (col-lg-10 col-md-10 col-xs-10). Just use col-10 and that will apply to all of the following breakpoints. And BS-5 doesn't use xs - that was for Bootstrap 3.

Placing text on top of vertical rule using CSS

I want to place OR text on top of the vertical rule(border-right) as shown in the image. No idea how to place it.
.left_col {
border-right: 1px solid black;
}
<div class="container mt-5">
<div class="row">
<div class="col-md-6 left_col">
/* left column content */
</div>
<div class="col-md-6">
/* right column content */
</div>
</div>
</div>
You can absolutely position a pseudo element:
.left_col {
position: relative;
border-right: 1px solid black;
}
.left_col:after {
content: 'or';
display: inline-block;
padding: 0.25em 0.5em;
position: absolute;
top: 50%;
left: 100%;
transform: translate(-50%, -50%);
background: orange;
}
/*following just for this demo not needed*/
.row {
display: flex;
}
.col-md-6 {
height: 100px;
width: 50%;
}
<div class="container mt-5">
<div class="row">
<div class="col-md-6 left_col">
/* left column content */
</div>
<div class="col-md-6">
/* right column content */
</div>
</div>
</div>
why don't you do this?
<div class="container mt-5">
<div class="row">
<div class="col-md-6 left_col">
<span>OR<span>
/* left column content */
</div>
<div class="col-md-6">
/* right column content */
</div>
</div>
</div>
in your css
.left_col {
position: relative;
}
span{
position: absolute;
top: 40%;
right: -10px;
}

Resize image in ionic cards

I want display a set of images with a description below. I chose to use Ionic cards.
I got this result (the first image):
While I want to preserve the same layout I have now, and add a description.
Here is my code:
<ion-content ng-controller="cityController">
<div class="row">
<div class="col col-33">
<div class="list card">
<div class="item item-body">
<img class="full-image"src="img/images/opera.jpg"/>
This is a "Facebook" styled Card..
</div>
</div>
</div>
<div class="col col-33">
<img src="img/images/basilique.jpg"/>
</div>
<div class="col col-33">
<img src="img/images/hoteldeville.jpg"/>
</div>
</div>
.center {
text-align: center;
}
.col {
overflow: hidden;
}
.row {
overflow: hidden;
height: 180px;
}
.fullscreen {
width: 100%;
height: 100%;
}
How can I fix this?
UPDATE
You have to change your source little bit.
Example HTML:
<div class="row">
<div class="col col-33">
<img class="full-image" src="http://www.w3schools.com/css/img_fjords.jpg"/>
<div class="card-description">This is a "Facebook" styled Card..</div>
</div>
<div class="col col-33">
<img class="full-image" src="http://www.w3schools.com/css/img_forest.jpg"/>
<div class="card-description">This is a "Facebook" styled Card..</div>
</div>
<div class="col col-33">
<img class="full-image" src="http://www.w3schools.com/css/img_mountains.jpg"/>
<div class="card-description">This is a "Facebook" styled Card..</div>
</div>
</div>
Example CSS:
.col-33 {
width: 33%;
float:left;
}
.full-image {
width: 100%;
height: 100%;
}
.card-description {
text-align: center;
}
Live demo here
This is just an example how it can work.
UPDATE:
To have the images full sized, you need to put the description over it.
In that case this CSS is required.
.col-33 {
width: 33%;
float:left;
position: relative;
}
.full-image {
width: 100%;
height: 100%;
}
.card-description {
position: absolute;
bottom: 0;
left: 0;
right: 0;
text-align: center;
padding: 5px;
line-height: 1.5;
background-color: rgba(255, 255, 255, 0.6);
}

CSS: Wrapping Divs

I have a CSS menu using the checkbox:checked trick here
But my issue is that when the menu is open, the content overflows off the side of the parent div - How do I make the divs fluid so that that wrap around to the next row and push each other along?
I have looked at Flexible Boxes, I have never used them before, but feel this could be the right track.
I have created a JSFiddle that illustrates what I am trying to do.
Thank you :)
EDIT
I've done some experimenting and it is the magic combination of padding and box-sizing - I've also just stumbled upon this useful post => International box-sizing Awareness Day
EDIT
HTML:
<div id="content">
<input type="checkbox" />
<div id="container">
<div class="item">Hello</div>
<div class="item">Hello</div>
<div class="item">Hello</div>
<div class="item">Hello</div>
<div class="item">Hello</div>
<div class="item">Hello</div>
<div class="item">Hello</div>
</div>
</div>
CSS:
#content {
width: 500px;
background: blue;
}
input[type="checkbox"]:checked ~ #container {
transition: left 1s;
left: 250px;
}
#container {
position: relative;
transition: left 1s;
left: 0px;
width: 100%;
}
.item {
display: inline-block;
width: 50px;
background: red;
margin: 4px;
}
The problem is that you are moving the left value of offset menu, which moves the menu item to left 250px. Similar thing will occur if you use margin-left property, because of width:100%.
instead, if you increase the padding, which will cause the increment inwards and reduce width of parent container, causing the item elements to fall on next life if no space is found.
Check the below snippet, where i am changing the padding value
* {
box-sizing: border-box;
}
#content {
width: 500px;
background: blue;
}
input[type="checkbox"]:checked ~ #container {
transition: padding 1s;
padding-left: 250px;
}
#container {
position: relative;
transition: padding 1s;
left: 0px;
width: 100%;
padding-left: 0;
}
.item {
display: inline-block;
width: 50px;
background: red;
margin: 4px;
}
<div id="content">
<input type="checkbox" />
<div id="container">
<div class="item">
Hello
</div>
<div class="item">
Hello
</div>
<div class="item">
Hello
</div>
<div class="item">
Hello
</div>
<div class="item">
Hello
</div>
<div class="item">
Hello
</div>
<div class="item">
Hello
</div>
</div>
</div>
The problem is that you're moving the whole container so everything inside it moves too.
What you actually want to do is move the first .item.
input[type="checkbox"]:checked ~ #container .item:first-child {
transition: margin-left 1s;
margin-left: 250px;
}
#content {
width: 500px;
background: blue;
}
input[type="checkbox"]:checked ~ #container .item:first-child {
transition: margin-left 1s;
margin-left: 250px;
}
#container {
position: relative;
}
.item {
display: inline-block;
width: 50px;
background: red;
margin: 4px;
}
<div id="content">
<input type="checkbox" />
<div id="container">
<div class="item">
Hello
</div>
<div class="item">
Hello
</div>
<div class="item">
Hello
</div>
<div class="item">
Hello
</div>
<div class="item">
Hello
</div>
<div class="item">
Hello
</div>
<div class="item">
Hello
</div>
</div>
</div>
As per your JSFiddle example you have to change few properties :
HTML : one line has to added for clear the floating
<div id="content">
<input type="checkbox" />
<div id="container">
<div class="item">
Hello
</div>
<div class="item">
Hello
</div>
<div class="item">
Hello
</div>
<div class="item">
Hello
</div>
<div class="item">
Hello
</div>
<div class="item">
Hello
</div>
<div class="item">
Hello
</div>
<div style="clear:both"></div>
</div>
</div>
And the CSS would be :
#content {
width: 500px;
background: blue;
}
input[type="checkbox"]:checked ~ #container {
transition: margin-left 1s;
margin-left: 250px;
}
#container {
position: relative;
transition: margin-left 1s;
margin-left: 0px;
}
.item {
display: inline-block;
width: 50px;
background: red;
margin: 4px;
}

Better way to absolutely position boxes to the left and right?

Is there a better way to absolutely position a bunch of boxes to the left and right like this? Perhaps using flexbox?
http://jsfiddle.net/frank_o/zpv4jbmx/
HTML:
<div class="box first">
<h1>Lipsum</h1>
</div>
<div class="box second">
<h1>Lipsum</h1>
</div>
...
CSS:
.box {
position: absolute;
background: blue;
color: white;
}
.box.first, .box.third, .box.fifth {
left: 20px;
}
.box.second, .box.fourth, .box.sixth {
right: 20px;
}
.box.first {
top: 20px;
}
.box.second {
top: 120px;
}
...
Since we are going for "better", you could use floating and CSS even/odd rules, like so:
HTML
<div class="box">
<h1>Lipsum</h1>
</div>
<div class="box">
<h1>Lipsum</h1>
</div>
<div class="box">
<h1>Lipsum</h1>
</div>
<div class="box">
<h1>Lipsum</h1>
</div>
<div class="box">
<h1>Lipsum</h1>
</div>
<!-- As many as you'd like... -->
CSS
.box {
background: blue;
color: white;
}
.box:nth-child(odd){
float: left;
clear: both;
}
.box:nth-child(even){
float: right;
clear: both;
}
The result is the same, but the implementation is much more scalable.
http://jsfiddle.net/9mcgvqLj/

Resources