I have a list of div elements with a big letter (A, B, C or D) and span (description) inside. I would like to center these span elements horizontally respect to each parent div, but keeping a fixed distance among all big letters. I'm looking for something like this:
The centering part is done with:
span{
position: absolute;
left: 50%;
transform: translateX(-50%);
}
But when I apply a simple transition (opacity for example) to div elements, the first letter in span elements is moved from it's place. If I remove the transition or transform property the issue goes away, but I need both (transform for centering).
Question: How to fix the issue with transition and transform, or how to center span elements without transform, but keeping the fixed distance among big letters?
Here is the code, and a DEMO:
HTML:
<div class="elements">
<div>A<span>Description</span></div>
<div>B<span>Really Long Description</span></div>
<div>C<span>Description</span></div>
<div>D<span>Description</span></div>
</div>
SCSS:
.elements{
margin-left: 50px;
div{
position: relative;
display: inline-block;
font-size: 40px;
margin: 0 10px;
opacity: 0.7;
transition: 0.3s;
&:hover{
opacity: 1;
span{
opacity: 1;
}
}
span{
position: absolute;
top: 100%;
left: 50%;
transform: translateX(-50%);
transition: 0.3s;
font-size: 15px;
white-space: nowrap;
pointer-events: none;
opacity: 0;
}
}
}
Depending on compatibility requirements, you could always use the flex box model, and it's handy justify-content property, like so:
.elements {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex; /*Only one out of the above that's really needed...*/
justify-content: space-around;/*Only one out of the below that's really needed...*/
-ms-flex-pack: distribute;
justify-content: space-around;
}
.elements >div {
position: relative;
display: inline-block;
opacity: 0.7;
font-size: 30pt;
text-align: center;
transition: 0.3s opacity;
}
.elements >div:hover {
opacity: 1;
}
.elements >div >div {
font-size: 12pt;
white-space: nowrap;
}
<div class="elements">
<div>A
<div>Description</div>
</div>
<div>B
<div>Long Description</div>
</div>
<div>C
<div>Description</div>
</div>
</div>
Your question has a very nice solution, tables! While they should only be used for tabular data semantically, they do have some nice display properties, and they'be been used since forever so compatibility is not an issue.
body{
display:table;
table-layout:fixed;
}
.elements{display:table-row;}
.elements >div {
width:20%; /*100% / Number of cells*/
display:table-cell;
padding:0 10px; /*There needs to be a little spacing otherwise it looks bad :) */
opacity: 0.7;
font-size: 30pt;
text-align: center;
transition: 0.3s opacity;
}
.elements >div:hover {
opacity: 1;
}
.elements >div >div {
font-size: 12pt;
white-space: nowrap;
}
<div class="elements">
<div>A
<div>Description</div>
</div>
<div>B
<div>Long Description</div>
</div>
<div>C
<div>Description</div>
</div>
<div>D<div>Description</div></div>
</div>
I have not found a way to make work properly transition and transform properties (Firefox at least). But I found a way to center each span elements inside it parent div, keeping distance among big letters (A, B, C & D).
See the SOLUTION DEMO, and the code added (SCSS):
$div-width: 40px;
$span-width: 200px;
.elements{
div{
width: $div-width; // fixed width
text-align: center; // center text
span{
width: $span-width; // big fixed width
left: -($span-width/2 - $div-width/2); // -(200px / 2 - 40px / 2)
}
}
}
Related
so I have a div which is a card and content in it. I achieved to make it moves up a bit but the transition property seems to not work.
Here is the HTML code
<div class="card">
<p> Title </p>
</div>
and here is the CSS code
.card:hover {
position: relative;
top: -10px;
transition: 1s;
}
So basically there is multiple cards and it works well every card with the .card class moves up when the mouse is over it, but it moves instantaneously, the transition does not work. Does anyone knows how to fix it? have a great day
This is because you have specified the position and transition only in the :hover block of code, meaning the transition timing is not specified until after the hover has already occurred. In other words, only the item that changes on hover (the top value) should be in the :hover.
Specify the position and transition outside the :hover block, like this for example:
.card {
position: relative;
transition: 1s
}
.card:hover {
top: -10px;
}
You can use transform: translateY
try this
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.box {
border: 1px solid black;
width: 150px;
height: 150px;
cursor: pointer;
transition: all .5s ease-in-out;
}
.box:hover {
transform: translateY(-10px);
}
<div class="box"></div>
Instead of playing with top which requires a positon attribute to move it out of flow, just add a margin to displace the element:
.card:hover {
margin-top: -20px;
margin-bottom: 20px;
transition: 1s;
}
/* for visualization purpose only */
body {
padding-top: 50px;
}
div {
border: 2px solid black;
display: flex;
justify-content: center;
align-items: center;
height: 40vh;
width: 10vw;
}
<div class="card">Card</div
I have a block called case-card which consists of a child div called case-card__wrapper that houses text.
On case-card hover, I want the case-card__wrapper to move up slightly. Not in one action, but as transition.
I feel like I have the general idea, but unsure on how to get the transition to work? At the moment, it just phases from one spot to another:
.case-card {
height: 560px;
width:600px;
color: #ededed;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
position: relative;
transform: translateY(20px);
transition: all .3s ease-in-out;
background-color: #333;
overflow: hidden;
}
.case-card__wrapper{
position: absolute;
transition: 0.5s;
/*top: 0; Don't want to add this because I want the text to be centered in the div and rather not define a number since the div heights may vary */
}
.case-card__title{
font-size: 16px;
}
.case-card:hover .case-card__wrapper {
top: 150px;
}
<div class="case-card">
<div class="case-card__wrapper">
<h4 class="case-card__title">Title</h4>
<p class="case-card__subtitle">Subtitle</p>
</div>
</div>
I'm trying to do this just via CSS. Any ideas?
If you cannot set initial value simply use transfrom. You can also remove position:absolute
.case-card {
height: 560px;
width:600px;
color: #ededed;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
position: relative;
transform: translateY(20px);
transition: all .3s ease-in-out;
background-color: #333;
overflow: hidden;
}
.case-card__wrapper{
transition: 0.5s;
}
.case-card__title{
font-size: 16px;
}
.case-card:hover .case-card__wrapper {
transform:translateY(-100%);
}
<div class="case-card">
<div class="case-card__wrapper">
<h4 class="case-card__title">Title</h4>
<p class="case-card__subtitle">Subtitle</p>
</div>
</div>
Here is a snippet of my Project Code:
body {
height: 100%;
margin: 0;
padding: 0;
font-family: 'Montserrat', sans-serif;
font-size: 16px;
}
input, button {
font-family: 'Montserrat', sans-serif;
}
.img_main_container {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
.centered {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.btn_sign_up, .btn_login:hover {
background: #5d8ffc;
color: #fff;
border: 1px solid #5d8ffc;
border-radius: 5px;
display: block;
width: 300px;
height: 40px;
transition: 0.3s;
-webkit-transition: 0.3s;
-moz-transition: 0.3s;
}
.btn_login, .btn_sign_up:hover {
background-color: Transparent;
background-repeat:no-repeat;
color: #ffffff;
border-radius: 5px;
display: block;
width: 300px;
height: 40px;
cursor:pointer;
overflow: hidden;
outline:none;
transition: 0.3s;
-webkit-transition: 0.3s;
-moz-transition: 0.3s;
}
<!DOCTYPE html>
<html>
<body>
<div class="img_main_container">
<img src="https://natgeo.imgix.net/subjects/headers/ND%20header%20(1).jpg?auto=compress,format&w=1920&h=960&fit=crop" alt="Storm" style="width:100%;">
<div class="centered">
<button class="btn_sign_up">Sign up</button>
<button class="btn_login">Login</button>
</div>
</div>
</body>
</html>
Everything works as you can see. But I want that the two buttons are side by side like this in that image here:
I tried so many examples but nothing worked. And I still can't figure out what's wrong here. It would be great if anyone could help. Thanks in advance. :)
Since you are using display:block on your buttons (.btn_sign_up, .btn_login), you can't make two buttons side by side, because block covering whole horizontal section.
Instead of this use display:inline-block and you will have buttons side by side.
More information you can get on the W3Schools
Flexbox would be a good solution for this. Add display: flex to the .centered class. This will place direct children of .centered side by side.
.centered {
display: flex;
}
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
Use Flexbox for this issue.This is the better solution. Add display: flex to the .centered class.
.centered { display: flex; align-items: center}
I am using a flexbox as my navigation bar at the top of my page. I have only included the code for this part because the project is an entire site. All anchor tags on my site are styled the same, with the same transform: scale(1.2) characteristic on hover. This works everywhere except in my nav. Nothing seems to scale at all inside of my nav.
Additionally on this codepen, the flexbox doesn't seem to respect the justify-content: space-around, making the anchors appear more squished together than they do on my actual site.
Codepen: https://codepen.io/colesam/pen/YxLPVW
a {
color: #646c84;
font-weight: 500;
line-height: 1.7vw;
transition: all 0.2s;
}
a:hover {
color: #ffaf54;
cursor: pointer;
transform: scale(1.2);
text-decoration: none;
}
a:focus {
color: #646c84;
text-decoration: none;
}
a:focus:hover {
color: #ffaf54;
cursor: pointer;
}
.active-indicator {
background: #ffaf54;
border-radius: 25px;
height: 2px;
margin-top: -2px;
margin-bottom: 5px;
margin-left: auto;
margin-right: auto;
opacity: 0;
transition: all 0.2s;
width: 25px;
}
.active-indicator.active {
opacity: 1;
}
#menu {
background: whitesmoke;
border: 1px solid rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: row;
justify-content: space-around;
padding: 0 25vw;
position: fixed;
left: -1;
right: -1;
top: 0;
transition: all 0.2s;
z-index: 1;
}
#menu a {
font-size: 0.9vw;
}
#menu.inactive {
opacity: 0;
}
<div id="menu">
<div id="landing-nav">
<a>Home</a>
<div class="active-indicator active"></div>
</div>
<div id="about-nav">
<a>About</a>
<div class="active-indicator"></div>
</div>
<div id="portfolio-nav">
<a>Portfolio</a>
<div class="active-indicator"></div>
</div>
<div id="resume-nav">
<a>Resume</a>
<div class="active-indicator"></div>
</div>
<div id="contact-nav">
<a>Contact</a>
<div class="active-indicator"></div>
</div>
</div>
Your nav menu has no extra width, so the flex items are packed together.
Yes, you create the illusion of width with:
#menu { padding: 0 25vw; }
But that just adds padding to the left and right of the container. The items are still packed together, and justify-content has no space to work.
revised codepen (padding removed)
Instead of padding, try using something like width: 50vw.
revised codepen (padding removed; width added)
The problem with the transform: scale() is that you have it applied to an inline-level element (a), which is not a transformable element.
Either add display: block to the anchor elements, or apply the transform to the parent div.
revised codepen (padding removed; width added; added display: block to a elements)
References:
https://drafts.csswg.org/css-transforms/#transform-property
https://drafts.csswg.org/css-transforms/#transformable-element
You have used invalid property values for your fixed nav.
Replace
left: -1;
right: -1;
with
left: 0;
right: 0;
I'm not sure why exactly transform: scale is not working, but it can be fixed by changing the display value of the div wrapping the anchor tags to flex
Codepen
Problem:
Hover cursor over the X and wait until the div is fully collapsed.
Move away from the X
Observe how div jumps to the bottom and straight back up.
Question:
How can I make the div expand without the font wrapping during the animation. ( I'm using a delayed font-size now, which seems to be problematic ).
Constrains:
These constrains are in effect due to the broader design of this isolated snippet.
Can not disable wrapping on outer div ( except for during the animation ).
Can not add a fixed width or height to the inner div.
Can not use JS
More context:
I'm using white-space:nowrap for the hover state so the text doesn't wrap while the div collapses. I then use a delayed font-size transition to prevent the text from wrapping while the div expands again ( since it's not possible to animate white-space or display ).
It seems like somehow the font-size of 0 get's lost for a fraction of a second at the beginning of the animation or something. Not sure exactly why it's jumping in the beginning.
.outer {
width: 300px;
overflow: hidden;
border: 1px solid red;
transition: width 2s;
}
.button {
padding: 0px 10px;
display:inline-block;
}
.outer:hover {
width: 30px;
white-space: nowrap;
}
.outer .inner {
font-size: 15px;
display:inline-block;
transition: font-size 0s 2s;
}
.outer:hover .inner {
font-size: 0px;
}
<div class="outer">
<div class="button">
X
</div>
<div class="inner">
This is the variable content of the box
</div>
</div>
You can:
add line-height: 22px; to .outer .inner; and
add height: 22px; to .outer.
.outer {
width: 300px;
height: 22px;
overflow: hidden;
border: 1px solid red;
transition: width 2s;
}
.button {
padding: 0px 10px;
display:inline-block;
}
.outer:hover {
width: 30px;
white-space: nowrap;
}
.outer .inner {
font-size: 15px;
line-height: 22px;
display:inline-block;
transition: font-size 0s 2s;
}
.outer:hover .inner {
font-size: 0px;
}
<div class="outer">
<div class="button">
X
</div>
<div class="inner">
This is the variable content of the box
</div>
</div>
.outer {
width: 300px;
overflow: hidden;
border: 1px solid red;
transition: width 2s;
}
.button {
padding: 0px 10px;
display: inline-block;
float: left;
line-height: 1;
}
.outer:hover {
width: 30px;
white-space: nowrap;
}
.outer .inner p {
font-size: 15px;
display: inline-block;
float: left;
transition: all ease-in-out 2s;
line-height: 1;
margin: 0;
}
.outer:hover .inner p {
font-size: 0px;
transition: all ease-in-out 1s;
}
<div class="outer">
<div class="button">
X
</div>
<div class="inner">
<p>This is the variable content of the box</p>
</div>
</div>
target the p, change the transition to all.
This is one of the problems you get when you change an object's size on hovering over itself. The trick to solving this is to use a parent container to hover on, which will always cover the width of the element, causing a slight ghosting effect, but compared to the visual effects your original solution had, this is much cleaner.
Your list of constraints isn't easy to work with, and the only way I can see this being solved under these circumstances is by making button and element that doesn't interfere with the document flow inside your container, so that nothing will wrap. Here are a few different attempts, one of which hopefully suiting your requirements:
solution fitting all contraints, using white-space
.outer-wrapper {
width: 350px;
}
.outer {
width: 350px;
overflow: hidden;
border: 1px solid red;
transition: width 2s;
}
.button {
width: 0;
height: 0;
}
.button:after {
content: 'X';
padding: 0px 10px;
display: inline-block;
}
.outer-wrapper:hover .outer {
width: 30px;
}
.outer .inner {
font-size: 15px;
display: inline-block;
margin-left: 2em;
transition: font-size 0s 2s;
white-space: nowrap;
}
.outer-wrapper:hover .outer .inner {
font-size: 0px;
}
<div class="outer-wrapper">
<div class="outer">
<div class="button"></div>
<div class="inner">
This is the variable content of the box
</div>
</div>
</div>
solution fitting all contraints, changing the markup to use pre
This solution introduces a pre element, which will prevent wrapping on it's own because it inherits a white-space:pre declaration from it's default style.
.outer-wrapper {
width: 350px;
}
.outer {
width: 350px;
overflow: hidden;
border: 1px solid red;
transition: width 2s;
}
.button {
width: 0;
height: 0;
}
.button:after {
content: 'X';
padding: 0px 10px;
display: inline-block;
}
.outer-wrapper:hover .outer {
width: 30px;
}
.outer .inner {
font-size: 15px;
display: inline-block;
margin-left: 2em;
transition: font-size 0s 2s;
}
.outer-wrapper:hover .outer .inner {
font-size: 0px;
}
pre {
font-family: inherit;
margin: 0;
}
<div class="outer-wrapper">
<div class="outer">
<div class="button"></div>
<div class="inner">
<pre>This is the variable content of the box</pre>
</div>
</div>
</div>
hacking your way out
You need to prevent the inner div's contents from wrapping, and if you don't want to do this via white-space, the only option left is to replace all whitespaces in it with non-breaking spaces to make sure the element can't wrap anymore:
<div class="inner">
This is the variable content of the box
</div>