on:hover to affect selector and its :after part - css

I've made a chat bubble with css:
.bubble
{
position: relative;
left: 20%;
width: 250px;
height: 185px;
padding: 0px;
background: #FFFFFF;
border: #817F7F solid 0px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
.bubble:after
{
content: "";
position: absolute;
top: 16.36px;
left: -9px;
border-style: solid;
border-width: 7px 9px 7px 0;
border-color: transparent #FFFFFF;
display: block;
width: 0;
z-index: 1;
}
I want to color the bubble and the pointy thingy when on :hover
.bubble:hover {
background:yellow;
}
only colors the .bubble, without .bubble:after.
How do I color the :after part?
here is fiddle

You need another rule to change the colors within the :after pseudo-element on :hover:
.bubble:hover:after {
border-color: transparent yellow;
}
Updated fiddle

Related

Horizontal CSS skew in Firefox blurs box element vertically

I am finding that applying a transform:skewX() to an element blurs its poition vertically(!) in Firefox. Does anyone know why, or how to fix this?
HTML
<div id="tab"><span>Tab</span></div>
<div id="content">Content</div>
CSS
#tab {
display: inline-block;
margin-left: 2em;
position: relative;
width: 3em;
text-align:center;
padding: .375em 0 0.125em;
}
#tab span {
position: relative;
z-index: 10;
}
#tab:before,
#tab:after {
position: absolute;
content: '';
top: 0;
width: 60%;
height: 100%;
border-top: 2px solid #999999;
background-color: #ffffff;
z-index: 1;
}
#tab:before {
left: 0;
transform: skewX(-20deg);
border-left: 2px solid #999999;
border-top-left-radius: 6px;
}
#tab:after {
right: 0;
transform: skewX(20deg);
border-right: 2px solid #999999;
border-top-right-radius: 6px;
}
#content {
border: 2px solid #999999;
border-radius: 6px;
padding: 4px;
margin-top: 0px;
}
The result is as below (zoomed image). Note the #content box's border showing through where they don't overlap, and the fuzziness at the top of the tab (both above and below the 2px width). By comparrison, when removing the skewX() for a straight tab, the border becomes pixel-perfect.
Is there any way to force the element's vertical pixel-alignment when it is subjected to a skewX() transform?

How can I create this button style?

I need to create the button styles in the image below (the one on the right is transparent, not white).
The bottom right corner is obviously the tricky part. It's not just a simple bevel; it's slightly rounded.
The best solution I've come up with is to apply an SVG image mask to a pseudo element positioned to the right of the button and reduce the right padding to compensate. But this approach has its limitations:
it requires a fixed height button (at least, if I want maintain the aspect ratio of the corner)
it requires a different SVG for each button size
I don't see how it can work for the transparent button style
So I'm hoping someone can suggest a different/better approach!
Thanks
UPDATE:
Here is my current approach - https://codepen.io/peteheaney/pen/jwVEPm
$primary: #FAB500;
*, *::after, *::before {
font-family: sans-serif;
box-sizing: border-box;
}
.button {
background-image: none;
border-width: 2px;
border-style: solid;
border-color: transparent;
cursor: pointer;
display: inline-block;
font-weight: bold;
margin-bottom: 0;
text-align: center;
text-decoration: none;
text-transform: uppercase;
touch-action: manipulation;
vertical-align: middle;
white-space: nowrap;
transition: all 0.2s;
&:active,
&:hover,
&:focus {
text-decoration:none;
}
&--large {
font-size: 15px;
padding-left: 24.818px;
height: 52px;
line-height: 52px;
border-top-left-radius: 6px;
border-bottom-left-radius: 6px;
position: relative;
margin-right: 24.818px;
&:after {
border-top: 2px solid $primary;
border-bottom: 2px solid $primary;
background: $primary;
content: "";
border-top-right-radius: 6px;
position: absolute;
left: 100%;
bottom: -2px;
width: 24.818px;
height: 52px;
mask: url(http://assets.peteheaney.com.s3.amazonaws.com/button-corner-right.svg) top left / cover;
}
}
&--primary {
color: #000;
background-color: $primary;
border-color: $primary;
&:active,
&:hover,
&:focus {
background-color: darken($primary, 2%);
border-color: darken($primary, 2%);
}
}
}
If you don't mind leaving the corner clickable, you could make the button invisible and just use a background image:
button{
width:x;
height:y;
border:none;
background-color:none
background-image:url(button_image.png);
background-position:center;
background-size:x y;
background-repeat:no-repeat;
}
With button_image.png being the image of your button style without text.
You can try to draw it like this using before and after :
.button {
position: relative;
display: inline-block;
background-color: orange;
color: white;
padding: 20px 40px;
font-size: 14px;
border-radius: 5px;
text-decoration: none;
}
.button:after {
content: '';
position: absolute;
z-index: 10;
display: block;
bottom: -6px;
right: -2px;
width: 10px;
height: 20px;
transform: rotate(45deg);
background-color: white;
}
.button:before {
content: '';
position: absolute;
z-index: 100;
display: block;
bottom: -1px;
right: 4px;
width: 13px;
height: 23px;
transform: rotate(45deg);
background-color: orange;
border-radius: 10px;
}
Button
Here is an example of how this could possibly be achieved with pure CSS.
However an image or an SVG might be a more efficient way to solve this issue.
.Large{
position:relative;
display:inline-block;
background:#FFB300;
border:none;
padding:20px 0 20px 30px;
border-radius:10px 0 0 10px;
height:40px;
font:700 1.5em/40px Arial;
}
.Large::after{
content:"";
display:block;
position:absolute;
top:0;
right:-30px;
width:30px;
height:50px;
background:#FFB300;
border-radius:0 10px 0 0;
}
.Large::before{
content:"";
display:block;
position:absolute;
bottom:0;
right:-30px;
width:0;
height:0;
border-top: 15px solid #FFB300;
border-right: 15px solid transparent;
border-bottom: 15px solid transparent;
border-left: 15px solid #FFB300;
}
<a class="Large">LARGE</a>
I am not really happy with my result, but here it goes just in case you can make it better.
The different color is just to make it easier to see what is what.
I have focused on solving the transparent one. Once you have it, solving the other is easier.
:root {
--width: 10px;
--width2: 14px;
}
.test {
position: relative;
margin: 20px;
width: 300px;
height: 150px;
position: absolute;
border: var(--width) solid transparent;
border-image: linear-gradient(to bottom right, orange 0%, orange 70%, transparent 70%);
border-image-slice: 1;
}
.test:before {
content: "";
position: absolute;
height: 25px;
width: 150px;
right: 29px;
bottom: -10px;
transform: skewX(-45deg);
border: solid 0px transparent;
border-bottom-color: red;
border-bottom-width: var(--width);
border-right-color: red;
border-right-width: var(--width2);
border-bottom-right-radius: 25px;
}
.test:after {
content: "";
position: absolute;
height: 50px;
width: 25px;
right: -10px;
bottom: 29px;
transform: skewY(-45deg);
border: solid 0px transparent;
border-bottom-color: red;
border-bottom-width: var(--width2);
border-right-color: red;
border-right-width: var(--width);
border-bottom-right-radius: 25px;
}
<div class="test"></div>
I decided to go for the approach I have demonstrated in this pen - https://codepen.io/peteheaney/pen/bRBOMq (compiled CSS version below)
*, *::after, *::before {
font-family: sans-serif;
box-sizing: border-box;
}
.button {
background-image: none;
border-style: solid;
border-top-width: 2px;
border-bottom-width: 2px;
border-left-width: 2px;
border-right-width: 0;
border-color: transparent;
cursor: pointer;
display: inline-block;
font-weight: bold;
margin-bottom: 0;
text-align: center;
text-decoration: none;
text-transform: uppercase;
touch-action: manipulation;
vertical-align: middle;
white-space: normal;
transition: all 0.2s;
}
.button:active, .button:hover, .button:focus {
text-decoration: none;
}
.button--large {
font-size: 15px;
padding: 16px 0 14px 21px;
border-top-left-radius: 6px;
border-bottom-left-radius: 6px;
position: relative;
margin-right: 21px;
}
.button--large:before {
content: "";
position: absolute;
left: 100%;
top: -2px;
width: 21px;
height: calc(100% - 17px);
border-top-right-radius: 6px;
}
.button--large:after {
position: absolute;
left: 100%;
bottom: -2px;
width: 21px;
height: 21px;
transition: all 0.2s;
}
.button--primary {
color: #000;
background-color: #FAB500;
border-color: #FAB500;
}
.button--primary:before {
background-color: #FAB500;
transition: all 0.2s;
}
.button--primary:active:before, .button--primary:hover:before, .button--primary:focus:before {
background-color: #f0ae00;
border-color: #f0ae00;
}
.button--primary:after {
content: url(http://assets.peteheaney.com.s3.amazonaws.com/button-corner-primary-large.svg);
}
.button--primary:active, .button--primary:hover, .button--primary:focus {
background-color: #f0ae00;
border-color: #f0ae00;
}
.button--secondary {
color: #000;
border-color: #FAB500;
}
.button--secondary:before {
border: 2px solid #FAB500;
border-bottom: 0;
border-left: 0;
transition: all 0.2s;
}
.button--secondary:active:before, .button--secondary:hover:before, .button--secondary:focus:before {
background-color: #FAB500;
}
.button--secondary:after {
content: url(http://assets.peteheaney.com.s3.amazonaws.com/button-corner-secondary-large.svg);
}
.button--secondary:active, .button--secondary:hover, .button--secondary:focus {
background-color: #FAB500;
border-color: #FAB500;
}
<a class="button button--large button--primary" href="">My button</a>
<a class="button button--large button--secondary" href="">My other button</a>
Firstly, I divided the right-hand portion into top and bottom (using :before and :after). The top-right pseudo element just has a background color and a top right border radius. This way the top-right portion can have a flexible height, meaning the buttons don't need to have a fixed height. The bottom right pseudo element is essentially an SVG ( using content: url(/path/to/svg.svg) ). This pseudo element always has a fixed width and height, so it maintains its size and aspect ratio regardless of the width/height of the button.
The outline style button is just a variation on the other style, with more borders and less backgrounds.
The only downside to this approach is the need for a different SVG for each button style. But I'm happy with that compromise.
Another take on Arthur's approach.
If you create the bottom right image (the white corner and the yellow corner border) you are able to position this so it stays to the bottom right and you have the rest of the button to style yourself.
button {
background-image:url(corner.svg);
height: 20px;
padding: 5px;
border-radius: 5px;
background-color: yellow;
background-repeat: no-repeat;
background-position: bottom right;
}

Creating a thick-to-slim border/box-shadow in css

How would I achieve the following as seen in the image below, in the best way as possible? I want a thick top border, but as it goes down I want the sides to become thinner and just "mend" (if that's right expression) into the black block.
This is my CSS code for the black block:
.containerMain {
background: #000;
padding: 15px;
border-radius: 5px;
width: 250px;
}
You can use the after pseudo-element to position an upside-down trapezoid behind your element.
Look here for a trapezoid shape example.
body { padding: 30px; }
.containerMain {
background: black;
padding: 15px;
border-radius: 5px;
width: 250px;
height: 250px;
position: relative;
}
.containerMain:after {
content: '';
border-radius: inherit;
margin: -20px;
margin-top: -25px;
width: 100%;
height: 50%;
position: absolute;
z-index: -1;
/* upside-down red trapezoid props */
border-top-width: 150px;
border-top-style: solid;
border-top-color: red;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
}
<div class="containerMain"></div>

define css arrow's degree

How would I define the degree of an arrow created with css follows
<div class="bubble"></div>
.bubble
{
background: none repeat scroll 0 0 #FF7401;
border: 3px solid silver;
border-radius: 25px;
bottom: 18px;
float: right;
height: 63px;
margin-right: 10px;
padding: 0;
position: relative;
width: 250px;
}
.bubble:after
{
content: '';
position: absolute;
border-style: solid;
border-width: 29px 16px 0;
border-color: #ff7401 transparent;
display: block;
width: 0;
z-index: 1;
bottom: -29px;
left: 47px;
}
.bubble:before
{
content: '';
position: absolute;
border-style: solid;
border-width: 31px 18px 0;
border-color: silver transparent;
display: block;
width: 0;
z-index: 0;
bottom: -34px;
left: 45px;
}
div.bubble p {
color: #FFFFFF;
font-size: 21px;
font-weight: bold;
margin-top: 10px;
text-align: center;
}
http://jsfiddle.net/lgtsfiddler/GpUpZ/1/
What I want is that the arrow's right edge right should be longer and not equal to the left edge. In particular, the left edge should be perpendicular to the text-bubble, and the right edge should come to meet it. For better visualization, here is an example of what I'm trying to achieve:
Modify your css as like this
.bubble:before
{
content: '';
position: absolute;
border-style: solid;
border-width: 33px 18px 0; // modify this line
border-color: silver transparent;
/* display: block; */ // remove this line
width: 0;
z-index: 0;
bottom: -27px; // modify this line
left: 50px;
-webkit-transform: rotate(-108deg) skew(11deg,-10deg); // modify this line
}
Demo
The shape and direction of the arrow is determined by the individual border widths and colors
A simple adjustment of individual values makes it easy to experiment. It's often also useful to write out the individual values for both widths and colors so see what's what.
JSfiddle Demo
CSS
.bubble {
background: none repeat scroll 0 0 #FF7401;
border: 3px solid silver;
border-radius: 25px;
bottom: 18px;
height: 63px;
margin: 50px;
padding: 0;
position: relative;
width: 250px;
}
.bubble:after {
content: '';
position: absolute;
border-style: solid;
display: block;
width: 0;
z-index: 1;
top:100%;
left: 47px;
}
.bubble.one:after { /* straight left side */
border-width: 29px 29px 29px 0;
border-color: #ff7401 transparent transparent transparent;
}
.bubble.two:after { /* straight right side */
border-width: 29px 0px 29px 29px;
border-color: #ff7401 transparent transparent transparent ;
}

Place arrow image on bottom border

Following is my jsfiddle in which I am trying to place an arrow image on the bottom border centerally aligned but I am unable to do that. Kindly let me know how to put an arrow image so its centrally aligned no matter what the width of the box is or height? Thanks
http://jsfiddle.net/wn7JN/463/
.bubble
{
position: relative;
width: 100px;
height: 50px;
padding: 0px;
background: #FFFFFF;
border: #000 solid 1px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}
.arrow:before
{
content: "";
position: absolute;
left: 50%;
border-style: solid;
border-width: 26px 26px 0;
border-color: #000 transparent;
display: block;
width: 0;
background-image:url(http://img2.wikia.nocookie.net/__cb20120818025551/merlin1/images/4/46/Drop_down_arrow.gif);
z-index: 0;
}
Try this. I add some changes check,
.bubble
{
position: relative;
width: 600px;
height: 50px;
padding: 0px;
background: #FFFFFF;
border: #000 solid 1px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}
.arrow:before
{
content: "";
position: absolute;
left: 50%;
bottom:-26px;
border-style: solid;
border-width: 26px 26px 0;
border-color: #000 transparent;
display: block;
width: 0;
z-index: 0;
margin:0 0 0 -26px;
}
replace the .arrow:before style & try it. it will align the arrow at center bottom.
.arrow:before
{
content: "";
position: absolute;
left: 50%;
top:100%;
margin-left:-26px;
border-style: solid;
border-width: 26px 26px 0;
border-color: #000 transparent;
display: block;
width: 0;
background:url(http://img2.wikia.nocookie.net/__cb20120818025551/merlin1/images/4/46/Drop_down_arrow.gif);
z-index: 0;
}

Resources