Properly transition shared borders - html

Is there a way, with css, to properly transition the border between two elements, while having a shared border (or some trick that simulates it)?
I am trying to get a situation like this (note: if there are any abhorrent wrong-doings in my css, please mention. I am not very experienced with css):
#container {
display: flex;
height: 128px;
width: 100%;
padding: 1em;
background-color: dimgray;
box-sizing: border-box;
}
a {
flex-grow: 1;
display: inline-block;
padding: 0;
line-height: 96px;
border: 0.1em solid #000000;
margin: 0 0 0 -0.1em;
border-radius: 0.12em;
box-sizing: border-box;
text-decoration: none;
font-family: "Roboto", sans-serif;
font-weight: 300;
color: #000000;
text-shadow: 0.08em 0.08em 0.08em rgba(0, 0, 0, 0.4);
background-color: #42cc8c;
text-align: center;
transition: all 0.5s;
}
a:hover {
text-shadow: 0 0 2em rgba(255, 255, 255, 1);
color: #ffffff;
border-color: #ffffff;
}
#container > :first-child {
margin: 0;
}
<div id="container">
button1
button2
</div>
Where the double border in between is "solved" by applying a negative margin (perhaps an alternative would be better?).
The middle border should:
stay white, when switching mouse hover from one button to the other
go from black to white, if neither was hovered before
go from white to black, when the mouse leaves the entire area
But in the above case, there are two overlapping borders, and one element is always on top. Playing with the z-index fails, when moving the mouse from one button to the next (instantly goes black, then transitions back to white). Setting no transition time for e.g. the left border fails, when moving the mouse in from the outside (left border is instant, obviously).
It's likely something, that should be assisted by javascript, but all too often, there is some trick, to achieve the desired behavior anyways.
As a note, the buttons in reality are vue router-link (and targeted by a class). I don't think that's too important though, but maybe switching to a table, and using border-collapse, or something similar, may work (didn't on basic tests).

After you hovered 1st button, you need to change a left border color of the second button.
#container {
display: flex;
height: 128px;
width: 100%;
padding: 1em;
background-color: dimgray;
box-sizing: border-box;
}
a {
flex-grow: 1;
display: inline-block;
padding: 0;
line-height: 96px;
border: 0.1em solid #000000;
margin: 0 0 0 -0.1em;
border-radius: 0.12em;
box-sizing: border-box;
text-decoration: none;
font-family: "Roboto", sans-serif;
font-weight: 300;
color: #000000;
text-shadow: 0.08em 0.08em 0.08em rgba(0, 0, 0, 0.4);
background-color: #42cc8c;
text-align: center;
transition: all 0.5s;
}
a:hover {
text-shadow: 0 0 2em rgba(255, 255, 255, 1);
color: #ffffff;
border-color: #ffffff;
}
a:hover:first-child+a {
border-left-color: #ffffff;
border-radius: 0 0.12em 0.12em 0;
}
#container> :first-child {
margin: 0;
}
<div id="container">
button1
button2
</div>

The solution would be to add a z-index to the :hover. I've also changed the negative margin to -0.2em.
z-index controls which elements show on top, setting it on :hover forces the element that receives the hover to appear on top (including its borders).
#container {
display: flex;
height: 128px;
width: 100%;
padding: 1em;
background-color: dimgray;
box-sizing: border-box;
}
a {
flex-grow: 1;
display: inline-block;
padding: 0;
line-height: 96px;
border: 0.1em solid #000000;
margin: 0 0 0 -0.2em;
border-radius: 0.12em;
box-sizing: border-box;
text-decoration: none;
font-family: "Roboto", sans-serif;
font-weight: 300;
color: #000000;
text-shadow: 0.08em 0.08em 0.08em rgba(0, 0, 0, 0.4);
background-color: #42cc8c;
text-align: center;
transition: all 0.5s;
}
a:hover {
text-shadow: 0 0 2em rgba(255, 255, 255, 1);
color: #ffffff;
border-color: #ffffff;
z-index: 999;
}
#container > :first-child {
margin: 0;
}
<div id="container">
button1
button2
</div>

Related

::after pseudo element overflowing element, using overflow:hidden; has extra space

I am trying to make a button with a hover effect and ::after pseudo class is involved.
The ::after pseudo-class covers 100% of the button's height and width, even more just to be sure; then when :hover, the ::after element's width will shrink to 0.
My problem is that I can't precisely size the ::after element, so I simply added overflow: hidden; to the button so that it will cut out the overflowing parts of the ::after pseudo-element. But it cropped a little too much, leaving one pixel between the border and the ::after pseudo-element covering the button.
.btn {
font-family: inherit;
background-color: transparent;
text-decoration: none;
padding: 1rem 1.5rem;
font-size: 2.3rem;
color: #fff;
border: solid 3px #EF9C43;
width: 50%;
border-radius: 100rem;
text-transform: uppercase;
font-weight: 400;
transition: color 0.3s, transform 0.3s, box-shadow 0.3s;
position: relative;
box-shadow: 1rem 1rem 4rem rgba(31, 31, 31, 0.5);
z-index: 5;
backface-visibility: hidden;
overflow: hidden;
}
.btn::after {
content: "";
position: absolute;
top: -2px;
left: -2px;
background-color: #EF9C43;
width: 110%;
height: 110%;
z-index: -1;
transition: width 0.3s;
}
.btn:hover {
font-weight: 600;
color: #1f1f1f;
transform: translateY(-0.3rem);
box-shadow: 1rem 1.5rem 2rem rgba(31, 31, 31, 0.6);
}
.btn:active {
transform: translateY(-0.1rem);
box-shadow: 1rem 1.25rem 2.5rem rgba(31, 31, 31, 0.5);
}
.btn:hover::after {
width: 0;
}
<button class="btn btn--orange">Hire our services</button>
Here is the codepen of my case: https://codepen.io/CoolBoiDave/pen/bGLdwxE
Any help would be appreciated! (PS: sorry for bad english)
I don't know why would you use an ::after pseudo element when all you need is to
transition a background-image.
Also, you could use an inset box-shadow instead of border.
.btn {
background-color: transparent;
padding: 1rem 1.5rem;
font: 400 2.3rem sans-serif;
text-transform: uppercase;
color: #fff;
border: 0;
border-radius: 4rem;
font-weight: 400;
transition: color .3s, background-position .3s, box-shadow .3s;
box-shadow: 0 1rem 4rem rgba(0,0,0,0.3), inset 0 0 0 3px #EF9C43;
background-image: linear-gradient(90deg, rgba(255,145,0,1) 50%, rgba(0,0,0,0) 50%);
background-size: 200%;
}
.btn:hover,
.btn:active {
background-position: 100%;
color: #1f1f1f;
box-shadow: 0 1.5rem 2rem rgba(0,0,0,0.3), inset 0 0 0 3px #EF9C43;
}
<button class="btn btn--orange">Hire our services</button>

Is it possible for the color to 'erase' the background in CSS?

I really doubt what I am asking is possible but it's still worth a try.
I am trying to create a button that normally has background-color: transparent; color: white; and when you hover over it, those properties should swap. The problem is that if you just swap them then all you see is a white button. If you know the background colour of the containing element then you can get the colour from there but If the button is over an image or a canvas then this won't work.
This is how I've been doing it so far
html,
body {
height: 100%;
}
#container {
background-color: #38404D;
height: 100%;
}
.ghost-button {
background-color: transparent;
border: 1px solid #ffffff;
outline: none !important;
transition: all 0.8s;
margin: 10px 10px;
padding: 6px 7px;
cursor: pointer;
color: #ffffff;
}
.ghost-button:hover {
background-color: #ffffff;
color: #38404D;
}
.ghost-button:active {
box-shadow: inset 0 0 8px 0px #888888;
}
<div id="container">
<button class="ghost-button">Hover Here</button>
</div>
UPDATE
It seems that quite a few people were confused by the question. I am asking if there is a way to do the exact same thing I've done above but on top of an image or a canvas (instead of a solid colour). See example below
html,
body {
height: 100%;
}
#container {
background-image: url("http://www.freegreatpicture.com/files/147/17878-hd-color-background-wallpaper.jpg");
height: 100%;
}
.ghost-button {
background-color: transparent;
border: 1px solid #ffffff;
outline: none !important;
transition: all 0.8s;
margin: 10px 10px;
padding: 6px 7px;
cursor: pointer;
color: #ffffff;
}
.ghost-button:hover {
background-color: #ffffff;
color: #38404D;
}
.ghost-button:active {
box-shadow: inset 0 0 8px 0px #888888;
}
<div id="container">
<button class="ghost-button">Hover Here</button>
</div>
Yes, it IS possible in CSS with mix-blend-mode.
Answer's update in April 2021: Currently it have a very solid support (95% globally) although Safari doesn't have hue, saturation, color, and luminosity blend modes. Of course, IE isn't a considerable thing if you expect to use it (like many of other cool CSS features of the last years).
.ghost-button {
/* Important part */
mix-blend-mode: screen;
background: #000;
color: #fff;
/* Button cosmetics */
border: .125em solid #fff;
font: 2em/1 Cursive;
letter-spacing: 1px;
outline: none !important;
transition: all .8s;
padding: .5em 1em;
cursor: pointer;
}
.ghost-button:hover {
/* Important part */
background: #fff;
color: #000;
}
#container {
background: url('http://www.freegreatpicture.com/files/147/17878-hd-color-background-wallpaper.jpg') center/cover;
/* Also works with background-color or gradients: */
/* background: linear-gradient(to right, red, yellow); */
/* Container positioning */
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
html, body {
margin: 0;
}
<div id="container">
<button class="ghost-button">Hover Here</button>
</div>
As you can see, the secret here is using mix-blend-mode: screen along with the black color for the "erased" part, since black is mixed with the background when using this screen mode.
No, it isn't possible in CSS! You could try to set the color with JS to mimic this effect.
body {
height: 100%;
}
#container {
background-color: #38404D;
height: 100%;
}
.ghost-button {
background-color: transparent;
border: 1px solid #ffffff;
outline: none !important;
transition: all 0.8s;
margin: 10px 10px;
padding: 6px 7px;
cursor: pointer;
color: #ffffff;
}
.ghost-button:hover {
background-color: none;
color: red;
}
.ghost-button:active {
box-shadow: inset 0 0 8px 0px #888888;
}
<div id="container">
<button class="ghost-button">Hover Here</button>
</div>
hover color is set to red you can update it.

Activating one button also affects the other?

Here's the demo: https://jsfiddle.net/krycLxb0/
The way this is set up is so that to create the illusion that the button is pressed, the padding of the outer container (.button) is changed, making the top padding more than the bottom. However, when this is activated, the other button seems to shrink down as well. Why does this happen, and how do I fix it?
Here's the source:
header {
letter-spacing: .04em;
font-weight: 900;
font-family: sans-serif;
}
.button {
padding: 4px;
padding-bottom: 12px;
border-radius: 6px;
display: inline-block;
transition: 300ms ease;
will-change: auto;
text-transform: uppercase;
text-align: center;
font-size: 14px;
text-shadow: 0px 4px 0px rgba(0, 0, 0, 0.2);
}
.button span {
display: inline-block;
width: 10em;
padding: 1.2em;
border-radius: 2px;
background: #FF4A50;
}
.button:hover {
box-shadow: 0px 6px 0px 0px rgba(0, 0, 0, 0.2);
}
.button:active {
transition: none;
padding-top: 12px;
padding-bottom: 4px;
}
.button--filled {
background: #BC2E56;
color: white;
}
.button--filled span {
background: #FF4A50;
}
.button--dark {
background: rgba(65, 57, 76, 0.6);
}
.button--dark span {
background: #FFF8F2;
}
<header>
<a class="button button--filled" href="#"><span>Get Started</span></a>
<a class="button button--dark" href="#"><span>Learn more</span></a>
</header>
Because your buttons are now vertical-align: baseline. Just add vertical-align: top; to your .button. See fiddle

Double box/border? Is this possible in CSS?

I'm trying to recreate this image in CSS.
This is what I got from experimenting, so far. I used box-shadow to act as the second box. I'm not sure if there's a better way to do this?
h4 {
font-family: sans-serif;
text-transform: uppercase;
text-align: center;
border: solid 3px black;
border-radius: 5px;
text-decoration: none;
font-weight: 600;
color: black;
letter-spacing: 2px;
padding: 20px 15px;
background: white;
box-shadow: 10px 5px 0px 0px #ffffff, 11px 7px 0px 2px #000000;
}
<h4>3. Scouting for a location</h4>
You can achieve this via absolutely position pseudo element. Also avoid property duplication via CSS inheritance.
.border {
text-align: center;
border: solid 3px black;
border-radius: 5px;
text-decoration: none;
font-weight: 600;
color: black;
letter-spacing: 2px;
padding: 20px 15px;
margin: 15px 15px;
background: white;
position: relative; /* new */
}
/* new */
.border:after {
content: "";
position: absolute;
display: block;
background: inherit;
border-radius: inherit;
border: inherit;
left: 2px;
top: 2px;
width: 100%;
height: 100%;
z-index: -1;
}
<div class="border">3. Scouting for a location</div>
The concept behind using box-shadow is that two shadows, one white and one black, overlap to simulate a second black border. But the black shadow is only visible in the direction from which it is offset from the white shadow, so a gap is apparent between the original border and the black shadow (as shown in the OP's original post).
The "spread radius" of the black shadow could be utilized to eliminate this gap (cleverly demonstrated by Nirav Joshi), but then the curvature of the corners is amplified and the two borders look different.
To duplicate the original border, I'd use ::after to generate an absolutely-positioned pseudo-element and use z-index to place it behind the original element. To further ensure that the border is duplicated exactly, I like Vadim Ovchinnikov's idea of inheriting the border color and radius from the original element.
.border {
position: relative;
text-align: center;
border: solid 3px black;
border-radius: 5px;
text-decoration: none;
font-weight: 600;
color: black;
letter-spacing: 2px;
padding: 20px 15px;
margin: 15px 15px;
background: white;
}
.border::after {
content: "";
position: absolute;
width: 100%;
height: 100%;
top: 3px;
left: 3px;
border: solid 3px black;
border-radius: 5px;
z-index: -1;
}
<h4 class="border">3. SCOUTING FOR A LOCATION</h4>
Try this example
Hope it will help you.
.border {
text-align: center;
border: solid 3px black;
border-radius: 5px;
text-decoration: none;
font-weight: 600;
color: black;
letter-spacing: 2px;
padding: 20px 15px;
margin: 15px 15px;
background: white;
-webkit-box-shadow: 3px 3px 0px 0px #ffffff, 3px 3px 0px 3px #000000;
-moz-box-shadow: 3px 3px 0px 0px #ffffff, 3px 3px 0px 3px #000000;
box-shadow: 3px 3px 0px 0px #ffffff, 3px 3px 0px 3px #000000;
}
<div class="border">Title</div>
EDIT
Here now you can see that i made box-shadow to 3px and no longer right side corner.
Use an absolute positioned ::after or ::before pseudo element and have its z-index lower than the element itself.

CSS error width?

I have the following issue:
I don't understand why if the input[type="submit"] style is deleted it keeps having 220px?
CSS code:
#popup_btn {
margin:0 15px 0 0;;
width:50px;
height:40px;
padding: 0;
}
Other CSS file:
.button, input[type="button"], input[type="reset"], input[type="submit"] {
background: none repeat scroll 0 0 rgba(0, 0, 0, 0) !important;
border: medium none;
border-radius: 0 !important;
box-shadow: none !important;
color: #fff;
font-size: 0.875rem;
font-weight: 700;
min-width: 220px;
padding: 1rem;
text-align: center;
text-shadow: none !important;
text-transform: uppercase;
transition: all 0.3s ease 0s;
width: 100%;
}
Maybe the wordpress does some stuff to it, but I can't understand...
It might be because you also have min-width set to 220px. Among, no matter what you say the width to, it won't be smaller than 220px. The solution might be to set width: 50px; min-width: 50px; wherever you want your element to be 50px