I have a design for a top-of-the-page dashboard in HTML that has the following requirements:
Everything should be vertically centered within the dashboard.
It should have a button in the exact center.
It should have text centered at the 25% and 75% marks.
It should have one last group of text all the way to the left.
Like this, but not with horrible colors:
I was able to achieve the top three goals (or very close to it) using display: flex and giving appropriate sizes to everything, like so:
HTML:
<div class="header">
<span class="left-text">LEFT TEXT</span>
<button class="button">BUTTON</button>
<span class="right-text">RIGHT TEXT</span>
</div>
CSS:
.header {
position: absolute;
top: 55px;
height: 40px;
width: 100%;
background-color: beige;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.button {
height: 26px;
width: 100px;
order: 2;
flex-grow: 0;
}
.left-text {
order: 1;
flex-grow: 1;
text-align: center;
}
.right-text {
order: 3;
flex-grow: 1;
text-align: center;
}
This last requirement, though, is really throwing me for a loop; without everything being nice and centered, I feel like flex is going to need some ugly adjustments. I feel like this would be much easier if I could layer div or span elements on top of each other however I liked, but something tells me I can't. Are there any good solutions for this problem? Am I close?
EDIT: added image of mockup.
Hopefully this will work for you, basically it adds the more-left class and positions it relative to the header, and you move it to the left as necessary, whatever is fitting.
HTML
<div class="header">
<span class="more-left">MORE LEFT</span>
<span class="left-text">LEFT TEXT</span>
<button class="button">BUTTON</button>
<span class="right-text">RIGHT TEXT</span>
</div>
CSS
.header {
position: absolute;
top: 55px;
height: 40px;
width: 100%;
background-color: beige;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.button {
height: 26px;
width: 100px;
order: 2;
flex-grow: 0;
}
.left-text {
order: 1;
flex-grow: 1;
text-align: center;
}
.right-text {
order: 3;
flex-grow: 1;
text-align: center;
}
.more-left {
position: relative;
left: 15%; /* adjust as neccessary */
}
I ended up ditching Flexbox entirely, going with absolute positioning and translate in order to get the results I wanted. Here's the final code:
HTML
<div class="header">
<span class="more-left v-center">MORE LEFT</span>
<span class="left-text abs-center">LEFT TEXT</span>
<button class="button abs-center">BUTTON</button>
<span class="right-text abs-center">RIGHT TEXT</span>
</div>
CSS
.header {
position: absolute;
top: 55px;
height: 40px;
width: 100%;
background-color: beige;
}
.v-center {
position: absolute;
top: 50%;
-webkit-transform: translateY(-50%);
-moz-transform: translateY(-50%);
-ms-transform: translateY(-50%);
-o-transform: translateY(-50%);
transform: translateY(-50%);
}
.h-center {
position: absolute;
-webkit-transform: translateX(-50%);
-moz-transform: translateX(-50%);
-ms-transform: translateX(-50%);
-o-transform: translateX(-50%);
transform: translateX(-50%);
}
.abs-center {
position: absolute;
top: 50%;
-webkit-transform: translate(-50%,-50%);
-moz-transform: translate(-50%,-50%);
-ms-transform: translate(-50%,-50%);
-o-transform: translate(-50%,-50%);
transform: translate(-50%,-50%);
}
.button {
height: 26px;
width: 100px;
left: 50%;
}
.more-text {
left: 10px;
}
.left-text {
left: 25%;
}
.right-text {
left: 75%;
}
EDIT: it occurred to me that you can't really combine v-center and h-center, because one of the transform entries will completely overwrite the other, instead of combining them. Hence the abs-center class.
Related
What I'm trying to achieve, once I reduce the size of the screen and some elements starts to move to a second line, keep them organized to the left, instead of centered (based on the number of elements on that row). This image might help
And this is my actual code, what I'm doing wrong?
#teamBoxesWrapper {
position: relative;
background-color: ;
width: 1200px;
height: auto;
left: 50%;
transform: translateX(-50%);
-webkit-transform: translateX(-50%);
-moz-transform: translateX(-50%);
-ms-transform: translateX(-50%);
-o-transform: translateX(-50%);
display: flex;
flex-flow: row wrap;
justify-content: space-between;
}
#teamUser {
width: 250px;
/* 20% of the viewport width */
height: 250px;
background-color: ;
margin: auto;
cursor: pointer;
margin-bottom: 20px;
position: relative;
}
.teamUser4 {
background-image: url('../images/empleado4.jpg');
background-position: center center;
background-size: cover;
}
<div id="teamBoxesWrapper">
<div id="teamUser" class="teamUser4">
<div id="teamUserPopup4" class="teamUserDetails">
<div id="teamUserTextAligner">
<h3 class="teamUserText1">Manuel Brenes</h3>
<hr class="userHr" />
<h3 class="teamUserText2">Graduado Social y
<br>Derechos Laborales</h3>
</div>
</div>
</div>
</div>
On your code try replacing your justify-content: space-between for center;
This question already has answers here:
How to center a "position: absolute" element
(31 answers)
Closed 5 years ago.
I'm centering an object with the following code:
.object {
width: 70%;
height: 70%;
position: absolute;
top: 50%;
left:50%;
/* these are the lines to which I will refer */
margin-top: -350px;
margin-left: -350px;
}
I'm using margin top and left to subtract the half of the object size but that size is given as a percentage. So my question is there is a way to assign these margins So that I don't have to change them manually every time I change the box size?
To me, best option you have is to use the transform:translate property.
.object {
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
No need ta calculate the width/2 and height/2 margin anymore.
And if you're using SASS, here is a magic #mixin to use :
#mixin transform($transforms) {
-moz-transform: $transforms;
-o-transform: $transforms;
-ms-transform: $transforms;
-webkit-transform: $transforms;
transform: $transforms;
}
#mixin center($position: "both") {
position: absolute;
#if $position == "vertical" {
top: 50%;
#include transform(translateY(-50%));
}
#if $position == "horizontal" {
left: 50%;
#include transform(translateX(-50%));
}
#if $position == "both" {
top: 50%;
left: 50%;
#include transform(translate(-50%, -50%));
}
}
Then, simply use
.object {
// both vertical and horizontal
#include center;
// only vertical
#include center(vertical);
// only horizontal
#include center(horizontal);
}
One of the many ways - use transform property to center the element - see demo below:
.object {
width: 70%;
height: 70%;
position: absolute;
top: 50%;
left:50%;
border: 1px solid red;
transform:translate(-50%, -50%);
}
<div class="object">Two</div>
You should use flex.
HTML
<body>
<div class="square"></div>
</body>
CSS
body{
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.square{
width: 200px;
height: 200px;
background-color: red;
}
.main_div{
width:200px;
height:200px;
border:thin black solid;
position:relative;
}
.main_div .object {
width: 70%;
height: 70%;
position: absolute;
transform:translate(-50%, -50%);
top: 50%;
left:50%;
border: thin red solid;
}
<div class="main_div">
<div class="object">Object Div Text</div>
</div>
Hope this helps.
Why not use margin: 0 auto?
.object {
width: 70%;
height: 70%;
position: absolute;
top:0;
left:0;
right:0;
bottom:0;
margin:0 auto;
}
https://jsfiddle.net/p9hy06tg/4/
I have a product div and whenever I hover over it, it rotated and shows the other side, it works and all but the thing is it becomes smaller, here's an idea of what it looks like here.
.product {
transform: scale(1.5);
transition: transform 1s cubic-bezier(.1, -.60, .50, 1.2);
perspective: 700px;
transform-style: preserve-3d;
}
.inner img {
height: 65px;
width: 65px;
}
.product:hover {
transform: rotateY(-180deg);
}
.product:hover .side-b {
transform: rotateY(180deg);
display: block;
}
.product:hover .side-a {
visibility: hidden;
}
.product-desc {
color: #fff;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
padding-left: 20px;
padding-right: 20px;
display: flex;
/* For centering text inside .photo-overlay */
flex-direction: column;
justify-content: center;
align-items: center;
display: none;
line-height: 0;
}
<li>
<div class="product">
<div style="height: 7px;visibility: hidden;"></div>
<div class="inner">
<img class="side-a" src="../images/test.jpg" alt="International Space Station">
<div class="product-desc side-b">
<h3>hi</h3>
buy
</div>
</div>
</div>
</li>
The resizing is because of your first rule transform: scale(1.5);. It tells the browser to initially resize the .product element to 50% more than its original size. But than on hover, you overwrite your transform- rule by only a rotation statement. Either delete this first rule or also use it in your :hover definition:
.product:hover {
transform: scale(1.5) rotateY(-180deg);
}
The transform: scale(1.5); created the problem!
Thanks to #Mohd Asim Suhail for pointing it out!
transform: scale(1.5); is creating problem for you, – Mohd Asim Suhail 3 mins ago
I have two identical elements. The top one, I'm scaling to double the size and then centering over the normal-sized one. I want its inner element to then be scaled back down to normal size and placed exactly where the normal sized element's inner element is placed.
This seems to be impossible. There seems to be no logic in the scaling + translation of position.
How would I do this?
https://jsfiddle.net/0urdrvao/
HTML:
<div class="top">
<div class="inner">
Inner
</div>
</div>
<div class="bottom">
<div class="inner">
Inner
</div>
</div>
CSS:
body, html
{
margin: 0px;
padding: 0px;
width: 100%;
height: 100%;
}
.top,
.bottom
{
position: relative;
top: 0px;
left: 0px;
width: 300px;
height: 300px;
background-color: gray;
z-index: 0;
}
.top
{
position: fixed;
transform-origin: 0 0 0;
transform: translate(-150px, -150px) scale(2);
opacity: .5;
z-index: 1;
}
.inner
{
position: relative;
top: 20vh;
left: 0px;
width: 100px;
height: 40px;
background-color: red;
}
.top .inner
{
/* This doesn't work */
transform: translate(150px,150px) scale(.5);
/* This also doesn't work (doing half)*/
/*transform: translate(75px,75px) scale(.5);*/
/* This also doesn't work (doing double)*/
/*transform: translate(300px,300px) scale(.5);*/
transoform-origin: 0 0 0;
background-color: yellow;
}
Since the top: 20vh will be scaled times 2, the transform-origin should be 0 -20vh.
When reverse a scale/translate you need to go backwards and start with scale and then the translate
.top{
position: fixed;
transform-origin: 0 0;
transform: translate(-150px, -150px) scale(2);
opacity: .5;
z-index: 1;
}
.top .inner{
transform: scale(.5) translate(150px, 150px);
transform-origin: 0 -20vh;
background-color: yellow;
}
Updated fiddle
Or one could do like this, setting origin to 0 0 and transform: scale(.5) translate(150px,150px) translateY(-20vh);
Updated fiddle
We are using some code to make a tooltip appear while hovering over text or an icon. Using a transform we are then able to center the tooltip, no matter what size it is, so we can have the size scale with the content of the tooltip: http://jsfiddle.net/z8wxdjzu/4/
.position-me {
margin: 10%;
}
.abbr {
position: relative;
}
.tooltip {
background: orange;
display: none;
text-align: center;
max-width: 100px;
padding: 3px;
position: absolute;
top: 20px;
left: 50%;
right: auto;
-webkit-transform: translate(-50%, 0);
-ms-transform: translate(-50%, 0);
transform: translate(-50%, 0%);
}
.abbr:hover .tooltip {
display: inline-block;
}
<div class="position-me">
<span class="abbr">
Text
<span class="tooltip">Lorem ipsum dolor sit amet.</span>
</span>
</div>
The problem is that even when providing a larger maximum width, a new line is added in the tooltip after every word. Instead we want the tooltip to fill the entire width (provided with max-width) before moving to a second line.
We don't want to set a fixed width, because some tooltips are rather short and we don't want a lot of empty space in the tooltip. How can we prevent the line breaks from happening?
EDIT: The max-width is actually important, since some of the tooltips are long enough to span several lines, so just removing it and using a whitespace: nowrap is going to be insufficient, unless we do manual line breaks, which I'd rather prevent.
The problem is that your tooltip span wants to have it's width be less or equal to the parent's width, in this case the span.abbr.
So to fix it we can add another div around the tooltip that is a bit larger but outside the flow of the other text, and it works.
Edit: I edited the snippet to center the tooltip. I also left in the red background for the surrounding div to show the trick that I apply here.
Example snippet:
.position-me {
margin: 10%;
}
.abbr {
position: relative;
}
.abbr div {
position: absolute;
top: 0;
left: 50%;
background-color: red;
width: 200px;
height: 2px;
}
.tooltip {
background: orange;
display: none;
text-align: center;
max-width: 100px;
padding: 3px;
position: absolute;
top: 20px;
-webkit-transform: translate(-50%, 0);
-ms-transform: translate(-50%, 0);
transform: translate(-50%, 0);
}
.abbr:hover .tooltip {
display: inline-block;
}
<div class="position-me">
Bla bla bla
<span class="abbr">
HOVER ME
<div><span class="tooltip">Lorem ipsum dolor sit amet.</span>
</div></span>
some more text here.
</div>
Here the fixed fiddle: Fiddle
You need to remove position:absolute and then add width:auto on .tooltip class and add display:inline-block; to .abbr:hover .tooltip
You can't prevent breaking (which you can do) without losing the max-width.
Just adding white-space:nowrap will stop the text breaking but will cause overflow of the span. So remove the max-width and all is good.
.position-me {
margin: 10%;
}
.abbr {
position: relative;
}
.tooltip {
background: orange;
/*display: none; */
/* disabled for demo */
text-align: center;
white-space: nowrap;
padding: 3px;
position: absolute;
top: 20px;
left: 50%;
-webkit-transform: translate(-50%, 0);
-ms-transform: translate(-50%, 0);
transform: translate(-50%, 0);
}
.abbr:hover .tooltip {
display: block;
}
<div class="position-me"> <span class="abbr">
Text
<span class="tooltip">Lorem ipsum dolor sit amet.</span>
</span>
</div>
i changed your css file this way and it worked !
.position-me {
margin: 10%;
}
.abbr {
//position: relative;//notice here
}
.tooltip {
background: orange;
display: none;
text-align: center;
//max-width: 100px;
padding: 3px;
position: absolute;
top: 20px;
left: 50%;
-webkit-transform: translate(-50%, 0);
-ms-transform: translate(-50%, 0);
transform: translate(-100%, 200%);//notice here !!!
}
.abbr:hover .tooltip {
display: block;
}
.position-me {
margin: 10%;
}
.abbr {
position: relative;
}
.tooltip {
max-width: 200px;
padding: 3px 8px;
color: #ffffff;
text-align: center;
text-decoration: none;
background-color: #000000;
border-radius: 4px;
display:none;
}
.abbr:hover .tooltip {
display:block;
}
<div class="position-me"> <span class="abbr">
Text
<span class="tooltip">Lorem ipsum dolor sit amet. rerterte rtertertert</span>
</span>
</div>
This should be the solution: http://jsfiddle.net/z8wxdjzu/7/