Reputation: 1325
So imagine you have 3 buttons next to each other.
In CSS you give it a style of a border of 3px and on hover that the border changes color. In render you see that the top and bottom, left, of first child, and right, of last child, borders are all 3px as set. But in between its 6px, as both buttons have there own border next to each other.
Lets call this a Situation-a
So to fix it you make it so every button, that is not first, would move the same -3px to the left so make it share the same border visualy.
But then on hover the first button right side of the border does not change the color as the button next to him is covering it.
Lets call this a Situation-b
But both solutons are wrong. What should happen is that the border between them is still 3px and on hover, no matter witch button, all borders around that 1 button would change color.
BUT HOW you do it?
Adding z-index
to the button with :hover
does NOT solve it since once you unhover, the border that is being overlapped instantly changes back the color while the rest of the borders slowly changes back the color.
Basically, buttons next to each other need to share the same border and on hover change the color of same border but to not create a 6px gap.
Here is a snippet of both Situations
* {
padding: 0;
margin: 0;
}
.parent {
font-size: 0;
margin: 10px;
}
.child {
font-size: 24px;
padding: 5px 15px;
border-radius: unset;
border: 3px solid black;
background-color: lightgray;
transition: border 0.25s ease-in-out;
}
.child:hover {
border: 3px solid cyan;
}
.situation-b .child:not(:first-child) {
margin-left: -3px;
}
Situation A (border between is 6px)
<div class="parent situation-a">
<button class="child">action a</button>
<button class="child">action b</button>
<button class="child">action c</button>
</div>
Situation B (on button A hover, right border is not seen)
<div class="parent situation-b">
<button class="child">action a</button>
<button class="child">action b</button>
<button class="child">action c</button>
</div>
Here is a created exmaple online of the issue: https://codesandbox.io/s/optimistic-dubinsky-1ji85?file=/index.html
Upvotes: 5
Views: 127
Reputation: 7690
You can also use z-index
in the transition property. It doesn't support easing the way other properties do but it DOES support the transition delay.
* {
padding: 0;
margin: 0;
}
.parent {
font-size: 0;
margin: 10px;
}
button {
position: relative;
font-size: 24px;
padding: 5px 15px;
border-radius: unset;
border: 3px solid black;
background-color: lightgray;
margin-right: -3px;
z-index:1;
transition: z-index 0s 1s, border 1s ease-in-out;
}
button:hover {
border: 3px solid cyan;
z-index: 10;
transition: z-index 0s, border 1s ease-in-out;
}
<div class="parent">
<button>action a</button>
<button>action b</button>
<button>action c</button>
</div>
Since a delay doesn't solve the actual layout issue and z-index is posing problems, there are other ways. Maybe this will help someone whose issue can't be solved by stacking elements.
In CSS we can use the Next sibling selector (+) to pick the NEXT DOM element of a type/class for interaction.
* {
padding: 0;
margin: 0;
}
.parent {
font-size: 0;
margin: 10px;
}
button {
position: relative;
font-size: 24px;
padding: 5px 15px;
border-radius: unset;
border: 3px solid black;
background-color: lightgray;
margin-right: -3px;
z-index:1;
transition: border 0.25s ease-in-out;
}
button:hover {
border-color: cyan;
}
/* next element in the dom */
button:hover + button {
border-left-color: cyan;
}
<div class="parent">
<button>action a</button>
<button>action b</button>
<button>action c</button>
</div>
Note: Due to the way borders render, this results in a strange cut-out look on larger border widths, so I'd probably solve this with a box-shadow
instead of a border on the elements.
Upvotes: 1
Reputation: 8439
If you've support for CSS grid, you can do something like the following:
.buttons {
display: grid;
grid-template-columns: repeat(3, 1fr);
column-gap: 3px;
width: 300px;
padding: 3px;
background-color: black;
}
button {
border: 0;
outline: 3px solid transparent;
transition: all 1s ease 0s;
}
button:hover {
outline-color: cyan;
}
<div class="buttons">
<button>action a</button>
<button>action b</button>
<button>action c</button>
</div>
The wrapping element, .buttons
, provides the black color as a background. Paired with padding and column-gap, it appears like the buttons have a 3px border. Use outline
which has no effect on document layout to allow the overlap during transition.
You can also do this with flexbox:
.buttons {
display: flex;
width: 300px;
padding: 3px;
background-color: black;
}
button {
flex: 1;
border: 0;
outline: 3px solid transparent;
transition: all 1s ease 0s;
}
button:not(:first-child) {
margin-left: 3px;
}
button:hover {
outline-color: cyan;
}
<div class="buttons">
<button>action a</button>
<button>action b</button>
<button>action c</button>
</div>
Upvotes: 3
Reputation: 605
You actually can do it with your z-index idea. You must only set position:absolute, position:relative, or position:fixed to element to work:
button {
border: 4px solid black;
height: 50px;
width: 100px;
border-radius: 0;
margin-left: -8px;
position: relative; /* Important */
}
button:hover {
border: 4px solid blue;
z-index: 2;
}
<div style="border-collapse: collapse;">
<button>aa</button>
<button>bb</button>
</div>
Upvotes: 0
Reputation: 207901
You can actually do it with the z-index. You just set a base z-index and put the transition on both the border and the z-index. See the example below where I exaggerated the transition time so that you can see that it works:
* {
padding: 0;
margin: 0;
}
.parent {
font-size: 0;
margin: 10px;
}
.child {
font-size: 24px;
padding: 5px 15px;
border-radius: unset;
border: 3px solid black;
background-color: lightgray;
transition: all 1s ease-in-out;
position: relative;
z-index:1;
}
.child:hover {
border: 3px solid cyan;
z-index:2;
}
.situation-b .child:not(:first-child) {
margin-left: -3px;
}
Situation A (border between is 6px)
<div class="parent situation-a">
<button class="child">action a</button>
<button class="child">action b</button>
<button class="child">action c</button>
</div>
Situation B (on button A hover, right border is not seen)
<div class="parent situation-b">
<button class="child">action a</button>
<button class="child">action b</button>
<button class="child">action c</button>
</div>
Upvotes: 3
Reputation: 551
I think all you were missing was position: relative;
so that z-index
was taken.
* {
padding: 0;
margin: 0;
font-size: 0;
}
.parent {
font-size: 0;
margin: 10px;
}
.child {
font-size: 24px;
padding: 5px 15px;
border-radius: unset;
border: 3px solid black;
background-color: lightgray;
transition: border 0.25s ease-in-out;
position: relative;
z-index: 1;
}
.child:hover {
z-index: 2;
border-color: red;
}
.situation-b .child:not(:first-child) {
margin-left: -3px;
}
<div class="parent situation-a">
<button class="child">action a</button>
<button class="child">action b</button>
<button class="child">action c</button>
</div>
<div class="parent situation-b">
<button class="child">action a</button>
<button class="child">action b</button>
<button class="child">action c</button>
</div>
Upvotes: -1