I'm new to flexbox and trying to make a menu using it.
I want links to have a nice border on the bottom when user hovers on them. But even if I set box-sizing: border-box; flex keeps recalculating text position and element 'jumps' instead of predicted behaviour.
I have an example with the problem. I don't want content inside my element to jump when I hover.
Is there any simple solution/edition to my code to make it work as expected? I know other ways of achieving what I want: set baseline, use relative/absolute positioning...
.item {
display: flex;
width: 200px;
height: 100px;
background: #123;
color: #fff;
text-align: center;
justify-content: center;
flex-direction: column;
}
.item:hover {
border-bottom: 10px solid lightgreen;
box-sizing: border-box;
}
<div class="item">
Content
</div>
By adding a 10px border on hover, you are changing the size of the box on hover. That will reposition surrounding elements... on hover.
One solution is to reserve the space for the border at all times. In other words, have the 10px border factored into the element in a normal state.
This border gets the element's background color (or transparent) so it is not visible. On hover, you only change the color.
.item {
display: flex;
width: 200px;
height: 100px;
background: #123;
color: #fff;
text-align: center;
justify-content: center;
flex-direction: column;
position: relative;
}
.item::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
width: 100%;
border-bottom: 10px solid #123;
}
.item:hover::after {
border-bottom: 10px solid lightgreen;
}
<div class="item">Content</div>
I would use an inset box-shadow for this feature.
I managed to recreate the effect by changing the :hover css to:
.item:hover {
box-shadow: inset 0 -10px lightgreen;
}
example here
What if you just set a bottom border by default using the same colour which is on its background? Once you hover over your item, you will need just to change the colour.
Related
I am trying to complete a style similar to the picture below me, whereby you have a left div partially in the background of a right div. Essentially, I want two side by side divs to be able to overlap each other, one in the background, and one in the foreground.
This is what I'm trying to achieve:
This is what I have so far:
.wrapper{
display: grid;
width: fit-content;
align-items: center;
grid-template-columns: 1fr auto;
border: solid 2px black;
}
.left{
width: 150px;
height: 115px;
background-color: red;
border: 2px red solid;
z-index:-999;
}
.right{
width: 120px;
height: 150px;
background-color: blue;
border: 2px blue solid;
z-index: 999;
}
<div class="wrapper">
<div class="left">
</div>
<div class="right">
</div>
</div>
I've tried using the z-index field to no avail. Also, in addition to being able to control which element is in the background; on mouse hover, I would like the left div in the background to "float" to the foreground and increase in size partially, and the right div to "float" to the back and partially decrease in size.
I hope my problem was adequately described, thank you.
I think the display: grid is not helping you here as it's trying to confirm the child divs into a grid (ie, not overlapping).
I would just set the two sides to have whatever width you want (eg 50%) and use z-index to overlay them.
See https://jsfiddle.net/47bh3eqk/2/
.wrapper {
max-width: 400px;
position: relative;
}
.left, .right {
width: 50%;
height: 200px;
position: absolute;
}
.left {
background-color: red;
left: 0;
}
.right {
background-color: blue;
right: 0;
z-index: 99;
-webkit-box-shadow: -4px 0px 15px -1px #000000;
box-shadow: -4px 0px 15px -1px #000000;
}
.home {
height: 100vh;
border: 0px solid rgb(255, 255, 255);
background-image: url(../img/b.jpg);
background-size: cover;
}
.home-content {
height: 80vh;
/* border: 4px solid red; */
}
.heading {
/* border: 2px solid red; */
height: 100%;
display: flex;
justify-content: center;
align-items: center;
font-size: 100px;
}
<section class="home">
<div class="home-content">
<div class="heading">
<div>Shubham karwal</div>
</div>
</div>
</section>
After removing border from .home the text Shubham karwal which was previously centered shifted towards left a bit.
What to do?
Please do help
You just have to add four lines to your css file:
.heading div {
height: 100%;
text-align: center;
}
Here is the example with the css added:
.home {
height: 100vh;
border: 0px solid rgb(255, 255, 255);
background-image: url(../img/b.jpg);
background-size: cover;
}
.home-content {
height: 80vh;
/* border: 4px solid red; */
}
.heading {
/* border: 2px solid red; */
display: flex;
height: 100%;
justify-content: center;
align-items: center;
font-size: 100px;
}
.heading div {
height: 100%;
text-align: center;
}
<section class="home">
<div class="home-content">
<div class="heading">
<div>Shubham karwal</div>
</div>
</div>
</section>
It depends on where the border is being added/removed. And also whether any other CSS settings are keeping the standard padding/margins that a browser might add to some elements or not.
The height is set at 100vh. If the box-sizing has not been altered it will default to value content, which means any padding and any borders are not included in the browser's calculation of the size of an element.
In the snippet given in the question neither the default padding/margins nor the default setting of box-zising are altered. Hence the height overall is greater than 100vh (what with the default top padding and the addition of a border) so space for a scroll bar is created on the right hand side and the text (well, the elements it is in) all shift a bit to the left.
Quite often you'll see these settings at the top of a style sheet:
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
which means all three of those settings are set as given for all relevant elements unless subsequently set.
Try this in your 'real' situation to see if it cures the problem.
I want to realize the following design with CSS. Here's the problem with the code below.
* {
box-sizing: border-box;
}
body {
margin: 50px;
}
a {
text-decoration: none;
}
.box {
display: flex;
width: 80px;
height: 200px;
writing-mode: vertical-lr;
border-radius: 20px 0 0 20px;
background: green;
}
.box-link {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
color: white;
border: 3px solid black;
border-radius: 20px 0 0 20px;
}
.box:hover {
background: white;
}
.box-link:hover {
color: black;
box-shadow: 0 0 0 10px white, 0 0 0 11px black;
}
<div class="box">
Hello, World!
</div>
That is, even if you hover the box-shadow part, the hover style is not applied.
I've seen solutions on some topics, but I can't finish the design I want to achieve in a little more. Also I cannot use pseudo-elements or add elements.
The code snippet draws a box-shadow on the outside, but you can even draw this inside the element (the inset of the box-shadow).
How to achieve rounded multiple lines without pseudo elements?
Outline radius?
How can I get multiple borders with rounded corners? CSS
Multiple Borders
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I can't replicate the layout below using CSS where the black border is offset and behind the picture:
I tried using the border property, but that obviously didn't work as I don't know if it's possible to offset it.
Ideally, I should also be able to move/animate that border so that the offset is reduced when hovering the image.
🔨 Simpler solution: Using box-shadow
If the background under your image has a single plain color, you can use box-shadow with 2 shadows:
html,
body {
height: 100vh;
margin: 0;
}
body {
background: yellow;
display: flex;
justify-content: center;
align-items: center;
}
.frame {
height: 75vh;
box-shadow:
10px -10px 0 -5px yellow,
10px -10px 0 0 black;
transition: box-shadow ease-in 150ms;
}
.frame:hover {
box-shadow:
5px -5px 0 -5px yellow,
5px -5px 0 0 black;
}
<img class="frame" src="https://cdn.motor1.com/images/mgl/7WjgW/s3/1974-lancia-stratos-hf-stradale-for-sale.jpg" />
🔥 Limitations when using box-shadow
If the background is not plain, you would not be able to properly mask the unwanted portion of your undermost shadow, so you will get something like this:
html,
body {
height: 100vh;
margin: 0;
}
body {
background: linear-gradient(cyan, yellow);
display: flex;
justify-content: center;
align-items: center;
}
.frame {
height: 75vh;
box-shadow:
10px -10px 0 -5px cyan,
10px -10px 0 0 black;
transition: box-shadow ease-in 150ms;
}
.frame:hover {
box-shadow:
5px -5px 0 -5px cyan,
5px -5px 0 0 black;
}
<img class="frame" src="https://cdn.motor1.com/images/mgl/7WjgW/s3/1974-lancia-stratos-hf-stradale-for-sale.jpg" />
🤯 Better but more complex solution: Using a wrapping element around the image with a pseudoelement with a border
The solution to the problem above would be to use a wrapping element around that image. That element would then have a pseudoelement (::beforeor ::after) with a border instead of a box-shadow.
To animate/move it, you would then use transform instead of changing the border itself:
html,
body {
height: 100vh;
margin: 0;
}
body {
background: linear-gradient(cyan, yellow);
display: flex;
justify-content: center;
align-items: center;
}
img {
height: 75vh;
display: block;
}
.frame {
position: relative;
}
.frame::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
box-sizing: border-box;
border: 5px solid black;
transform: translate(10px, -10px);
transition: transform 150ms;
}
.frame:hover::before {
transform: translate(5px, -5px);
}
<div class="frame">
<img src="https://cdn.motor1.com/images/mgl/7WjgW/s3/1974-lancia-stratos-hf-stradale-for-sale.jpg" />
</div>
Note that I have also added box-sizing: border-box. Otherwise, the ::before pseudoelement size would be the size of the parent + the width of the borders around it, so the border would look bigger than the image. When using box-sizing: border-box the size of the borders and paddings are subtracted from the total size instead.
🚀 Performance note
Have you noticed that the last example moves more smoothly and maybe faster than the other two? That's because your browser is now using hardware acceleration to move it, which was not the case before.
Therefore, if you need to move/animate that, I would advise you to use this method. Otherwise, if you have a plain background and the border is not animated, then you could use the box-shadow method, which involves just a few lines of CSS.
There might be a more elegant way but I would solve it like this:
.frame-wrapper {
display: inline-block;
position: relative;
}
.frame-wrapper::before {
content: '';
display: block;
z-index: -1;
position: absolute;
bottom: 5%;
left: 5%;
border: 4px solid black;
height: 100%;
width: 100%;
}
<div class="frame-wrapper">
<img src="https://via.placeholder.com/200x300" alt="">
</div>
Without seeing your code, it would be hard to tell where the issue is. But try putting your image in its own and applying a border to the div itself.
I am having trouble with the combination of the CSS selector :nth-child(...) and the box-shadow effect. The desired effect is as follows:
Even-numbered div elements in a container are given an alternating background color.
When the user hovers over one of the div elements, a box shadow is applied, giving the appearance of the "hovered" div "hovering" above the following div.
However, I am running into a problem. While the box shadow is applied to the "hovered" element, the effect is different for even-numbered div elements as opposed to odd-numbered ones. Essentially, the shadow of each even div overlaps the following odd div, while the shadow of each odd div is rendered behind the following even div.
This pen demonstrates the issue better: http://codepen.io/jtlovetteiii/pen/cEaLK
Here is the HTML snippet:
<div class="rows">
<div class="row"></div>
<div class="row"></div>
...
</div>
Here is the CSS:
.rows
{
background-color: #AAAAAA;
}
.rows .row:nth-child(even)
{
background-color: #E2E2E2;
}
.row
{
height: 20px;
cursor: pointer;
}
.row:hover
{
box-shadow: 0px 10px 10px #888888;
}
What am I missing?
The reason this is happening is because only your nth-child(even) divs have a background color. While it appears that the hover shadow is overlapping the other div, it really isn’t – it’s overlapping the parent’s background color.
You can fix the issue with a combination of position: relative and z-index:
.rows {
position: relative;
}
.row
{
position: relative;
height: 20px;
cursor: pointer;
background-color: #CCCCCC;
}
.row:nth-child(even)
{
background-color: #E2E2E2;
}
.row:hover
{
box-shadow: 0px 10px 10px #888888;
z-index: 100;
}
CodePen demo
Interesting. Not sure why that is happening, but I found a workaround. By adding a position: relative to the :hover elements, the hover effect is more consistent:
http://codepen.io/anon/pen/hsKEf
.rows
{
background-color: #AAAAAA;
}
.rows .row:nth-child(even)
{
background-color: #E2E2E2;
}
.row
{
height: 20px;
cursor: pointer;
}
.row:hover
{
box-shadow: 0px 10px 10px #888888;
position: relative;
}
It still doesn't look quite right, but maybe a margin offset would cause it to look a bit better.
JSFiddle
.row
{
height: 20px;
cursor: pointer;
position:relative;
z-index:1;
}
.row:hover
{
box-shadow: 0px 10px 10px #888888;
z-index:2;
}