Hovered background color change breaks simulated + display - css

I have a button with + and - symbols made with linear gradients and background size. If I add a hover state, just changing the color, the + and - effect doesn't work. Any idea why this happens?
This is the pen: https://codepen.io/miguelrivero/pen/gOraZaM
.AddToBagButton__decrease,
.AddToBagButton__increase {
background: linear-gradient(#2e8561, #2e8561) top left,
linear-gradient(#2e8561, #2e8561) top right,
linear-gradient(#2e8561, #2e8561) bottom left,
linear-gradient(#2e8561, #2e8561) bottom right;
background-repeat: no-repeat;
border: 13px solid #2e8561;
box-sizing: border-box;
border-radius: 50%;
&:hover {
background: linear-gradient(#215e45, #215e45) top left,
linear-gradient(#215e45, #215e45) top right,
linear-gradient(#215e45, #215e45) bottom left,
linear-gradient(#215e45, #215e45) bottom right;
border: 13px solid #215e45;
}
}
.AddToBagButton__decrease {
background-size: 100% calc(50% - .5px);
left: 0;
}
.AddToBagButton__increase {
background-size: calc(50% - 1px) calc(50% - .5px);
right: 0;
}

Any idea why this happens?
Because you are overwriting the background-size you specified for the buttons, by applying the changed gradient via the background shorthand property, which resets all individual background properties you did not specify, to their defaults. (.AddToBagButton__decrease:hover has a higher specificity, than .AddToBagButton__decrease.)
Make that
&:hover {
background-image: …
instead. (Gradients are considered images in CSS.)

Related

Is it possible to make a "double arrow" with css3 content technique?

Im looking for a way to recreate this button with CSS only.
I know about the triangle technique and I also know how to add a border to it, but unfortunately I don't know any way to recreate this button (without adding additional wrappers or using images).
The buttons I need this style on are <input["submit"]> and ordinary <a>'s.
With one element, you could do it using gradients and skewed pseudo-elements for a link:
demo
(you could actually do it using just gradients, but then a hover action won't be triggered on hover on the arrow shape itself, but on hover on the rectangular element containing it)
HTML:
<a class='boo' href='#'>click me</a>
Relevant CSS:
.boo {
display: inline-block;
position: relative;
padding: .5em 2em;
background:
linear-gradient(60deg, dodgerblue 50%, transparent 50%) 100% 0,
linear-gradient(-60deg, transparent 50%, dodgerblue 50%) 100% 100%,
linear-gradient(-90deg, transparent 1em, dodgerblue 1em);
background-repeat: no-repeat;
background-size: 1em 50%, 1em 50%, 100% 100%;
}
.boo:before, .boo:after {
position: absolute;
right: -.2em;
width: .5em; height: 50%;
background: dodgerblue;
content: '';
}
.boo:before {
top: 0;
transform: skewX(30deg);
}
.boo:after {
bottom: 0;
transform: skewX(-30deg);
}
EDIT:
If your background is a solid color, not an image or a gradient, you could do it in a much simpler way, without using gradients (which means that this second method also has the advantage of working in IE9).
demo #2
.boo {
display: inline-block;
position: relative;
padding: .5em 2em;
background: lightblue;
}
.boo:before, .boo:after {
position: absolute;
right: -.3em;
width: .5em; height: 50%;
box-shadow: -.2em 0 0 white;
background: inherit;
content: '';
}
.boo:before {
top: 0;
transform: skewX(30deg);
}
.boo:after {
bottom: 0;
transform: skewX(-30deg);
}
You should use a background image. Create a transparent png containing the arrow.
You would need two elements, the outer would contain the background image, the inner would contain the text, and a background color which is the same as the one on the arrow. Alternatively, you could use a second background image instead of a background color, for example if your button is not just a flat color.
The trick is to align the box containing the text with the background image.
If your arrow is 20px tall, your inner box could be e.g. 16px plus 2px padding on each side (search for box model if you would like to understand this better).
The outer element can have a right-margin set to the approximate width of the arrow image.
I hope this makes sense. The general technique is called sliding doors. I suggest reading the entire article if you have the time.

Can I make a color background take up only a % of an element without making an image?

If I want to have a blue bar in the background at the top of my webpage (so the body element's background), but I want it to be 100px in height and span the entire horizontal background... is there any way to do this without making a background image that is 100px with the color I want (and maybe 1px in width) and making it repeat-x?
Basically, rather than doing:
background: url("images/pagestripe.png") repeat-x;
I want to do this:
background: #FFCCFF 100px top left repeat-x;
Which would give me a 100px background of the color #FFCCFF that starts in the top left of the page and repeats horizontally.
Similarly, if I wanted it to repeat-y, it would make the 100px the width instead of the height.
The positioning markers can represent offsets...
Is this possible? Is there actual CSS code for what I am looking for? Perhaps I'm not far off...
You can do it using linear gradients:
body {
background-image: -moz-linear-gradient(top, blue 100px, transparent 0);
background-image: -o-linear-gradient(top, blue 100px, transparent 0);
background-image: -webkit-linear-gradient(top, blue 100px, transparent 0);
background-image: linear-gradient(top, blue 100px, transparent 0);
}
Edit: This is CSS3 only. For CSS2 you may try
body:before {
content: ' ';
display: block;
top: 0;
position: absolute;
height: 100px;
width: 100%;
background: blue;
}
You could make the bar a separate div and set a negative margin on it. Something like this:
<div id="bluebar"></div>
Content goes here...
And then in CSS:
div#bluebar {
background: #fcf; /* that's actually pink, but whatever... */
height: 100px;
margin-bottom: -100px;
}
I'd give a jsFiddle link, but they're apparently down for maintenance right now, so here's a simple static HTML demo instead.
Yes it can be done.
You can create a single full width element with the height and background color you desire.
Use CSS to position the element.
div#bluebar {
background: #acf;
display: block;
height:100px;
width:100%;
position: absolute;
top: 0px; /* however far from the top you would like it*/
left: 0px;
z-index: 10; /* or some other number that will place it below the appropriate elements */
}
Just be sure that the parent of #blubar does not have position:relative; set or it will position relative to the parent not the document.

background position for background color

Im able to give the start position of an background image. But if i give positions for solid fill background its not working.
Here is the js fiddle for that.
http://jsfiddle.net/yPVJE/
So can we set the start position and the size of an solid fill backgrounds?
Thanks!
I would take a similar approach to StuR, but using background position instead of gradient points. You can then set your background position as you would usually.
div {
background:linear-gradient(left, #000, #000) no-repeat 50px 50px;
}
This is one way to offset a solid background color, using a linear gradient with a transparent colour for the first x number of pixels:
.offset {
background-image: linear-gradient(left, transparent 300px,rgba(39,39,39,.5) 300px, rgba(39,39,39,.5) 100%);
width: 100%;
height: 500px;
}
Here's a demo on JSFiddle.
You can not offset a background color. Only background images have a position.
If you can make a ::before pseudo element with bg color, height and width and just offset it from its parent, you'll have complete control of its appearance. Much easier than putting a border in the pseudo element:
/* adding a ::before element with bg and border radius to create a
cropped circle to overlay parent bg image's blue right end */
.myElement::before {
background-color: #fff;
content: "";
margin: 0 auto;
position: absolute;
top: 43px;
right: 0;
width: 300px;
height: 201px;
z-index: -1;
border-top-right-radius: 8px;
border-bottom-right-radius: 8px;
}
Yes, with linear-gradient it works:
div { background-image: linear-gradient(transparent 10px, grey 10px); }
Watch out for improper alignment when linear-gradient points are used.
Here's a better approach:
background: linear-gradient(#6699cc, #6699cc);
background-size: auto 4em;
background-repeat: no-repeat;
It uses linear-gradient just to generate solid color, which is then resized to reflect the covered area size.
Also background-position could be used as needed, for example:
background: linear-gradient(#6699cc, #6699cc);
background-size: calc(100% - 30px) auto;
background-repeat: no-repeat;
background-position: right;
In the last example, the background color would 'start' 30px from the left of the div.
Further reading:
https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient
https://developer.mozilla.org/en-US/docs/Web/CSS/background-size
https://developer.mozilla.org/en-US/docs/Web/CSS/calc
https://developer.mozilla.org/en-US/docs/Web/CSS/background-repeat
https://developer.mozilla.org/en-US/docs/Web/CSS/background-position
You can use background-size instead of background-position to restrict the colored area:
// randomly set background size every 1 second
var elm = document.querySelector('div');
window.setInterval(()=> {
var randomValue = Math.random()*100;
elm.style.backgroundSize = randomValue + '%';
}, 1000)
div {
height: 100px;
border: 1px solid black;
transition: .4s ease-out;
background: linear-gradient(to right, black, black) no-repeat;
background-size: 0; /* <--- starting from 0% */
}
<div></div>
Another way to accomplish this would be to add a pseudo-element to the div element like so:
div {
::before {
border-top: 10px solid #0066a4;
content:"";
margin: 0 auto; /* this centers the line to the full width specified */
position: absolute; /* positioning must be absolute here, and relative positioning must be applied to the parent */
top: 12px; left: 0; right: 0; bottom: 0;
z-index: -1;
}
}
See this CodePen by Eric Rasch for a working example: https://codepen.io/ericrasch/pen/Irlpm
You can achieve this by having the parent element and child element position: relative;. Next, you can just go in and set offsets. There are a few other ways to achieve this but this is one of the many takes.
SCSS:
HTML:
EXAMPLE:
Note this might have side effects for buttons and links. Test it for your use case. Good luck!
Happy Coding

CSS limited background repeat (multiple background images)

I am trying to make a cool background effect (with alpha transparency and rounded corners) for a drop-down menu with a single CSS entry.
I have a top cap (180 x 4 px), a bottom cap (180 x 20px) and a repeating middle (180 x 2px).
Here is my existing relevant CSS:
background-image: url('images/drop_top.png'), url('images/drop_bottom.png'), url('images/drop_middle.png');
background-position:left top, left bottom, 0px 10px;
background-repeat:no-repeat, no-repeat, repeat-y;
The problem is that the middle section which needs to be expandable/tilable is repeating all the way under the top and bottom caps--such that my rounded corners are now square because they have the repeating middle under them.
Is there some way to prevent the multiple backgrounds from overlapping??
Thanks in advance!
Background-origin and/or background-clip should do the trick. Just set top & bottom borders equal to the height of your cap graphics, then set drop_middle to background-clip:padding-box
EDIT: Here is a complete solution, but for a horizontal orientation:
http://jsfiddle.net/nGSba/
#box
{
display: inline-block;
margin: 1em;
padding: 9px;
border-left:9px solid transparent;
border-right:9px solid transparent;
background-image: url(http://s11.postimage.org/ufpdknvjz/left.png),
url(http://s11.postimage.org/6ng294tj3/right.png),
url(http://www.css3.info/wp-content/themes/new_css3/img/main.png);
background-repeat: no-repeat, no-repeat, repeat-x;
background-position: left top, right top, left top;
background-origin: border-box,border-box,padding-box;
background-clip: border-box,border-box,padding-box;
}
What got me stuck was the transparent on the border-color. The background will always go under the border, so if your border is solid the background will still be invisible.
Whatever your element is that you are applying the images to, try doing the following (I'll assume div for sake of illustration):
div {
background-image: url('images/drop_top.png'), url('images/drop_bottom.png');
background-position:left top, left bottom;
background-repeat:no-repeat, no-repeat;
position: relative;
}
div:after {
position: absolute;
top: 10px ; /* whatever your top image height is */
bottom: 10px; /* whatever your bottom image height is */
left: 0;
right: 0;
z-index: -1;
background-image: url('images/drop_middle.png');
background-position: left top;
background-repeat: repeat-y;
}

Can I apply multiple background colors with CSS3?

I know how to specify multiple background images using CSS3 and modify how they are displayed using different options.
Currently I have a <div>, which needs to have a different color for about 30% of the width on the left side:
div#content {
background: url("./gray.png") repeat-y, white;
background-size: 30%;
}
Instead of loading the image which is totally gray, how can I do this specifying the color, and without additional <div>s?
Yes its possible! and you can use as many colors and images as you desire, here is the right way:
body{
/* Its, very important to set the background repeat to: no-repeat */
background-repeat:no-repeat;
background-image:
/* 1) An image */ url(https://placeimg.com/640/100/nature/John3-16),
/* 2) Gradient */ linear-gradient(to right, RGB(0, 0, 0), RGB(255, 255, 255)),
/* 3) Color(using gradient) */ linear-gradient(to right, RGB(110, 175, 233), RGB(110, 175, 233));
background-position:
/* 1) Image position */ 0 0,
/* 2) Gradient position */ 0 100px,
/* 3) Color position */ 0 130px;
background-size:
/* 1) Image size */ 640px 100px,
/* 2) Gradient size */ 100% 30px,
/* 3) Color size */ 100% 30px;
}
You can’t really — background colours apply to the entirely of element backgrounds. Keeps ’em simple.
You could define a CSS gradient with sharp colour boundaries for the background instead, e.g.
background: -webkit-linear-gradient(left, grey, grey 30%, white 30%, white);
But only a few browsers support that at the moment. See http://jsfiddle.net/UES6U/2/
(See also http://www.webkit.org/blog/1424/css3-gradients/ for an explanation CSS3 gradients, including the sharp colour boundary trick.)
You can use as many colors and images as you desire.
Please note that the priority with which the background images are rendered is FILO, the first specified image is on the top layer, the last specified image is on the bottom layer (see the snippet).
#composition {
width: 400px;
height: 200px;
background-image:
linear-gradient(to right, #FF0000, #FF0000), /* gradient 1 as solid color */
linear-gradient(to right, #00FF00, #00FF00), /* gradient 2 as solid color */
linear-gradient(to right, #0000FF, #0000FF), /* gradient 3 as solid color */
url('http://lorempixel.com/400/200/'); /* image */
background-repeat: no-repeat; /* same as no-repeat, no-repeat, no-repeat */
background-position:
0 0, /* gradient 1 */
20px 0, /* gradient 2 */
40px 0, /* gradient 3 */
0 0; /* image position */
background-size:
30px 30px,
30px 30px,
30px 30px,
100% 100%;
}
<div id="composition">
</div>
In this LIVE DEMO i've achieved this by using the :before css selector which seems to work quite nicely.
.myDiv {
position: relative; /*Parent MUST be relative*/
z-index: 9;
background: green;
/*Set width/height of the div in 'parent'*/
width:100px;
height:100px;
}
.myDiv:before {
content: "";
position: absolute;/*set 'child' to be absolute*/
z-index: -1; /*Make this lower so text appears in front*/
/*You can choose to align it left, right, top or bottom here*/
top: 0;
right:0;
bottom: 60%;
left: 0;
background: red;
}
<div class="myDiv">this is my div with multiple colours. It work's with text too!</div>
I thought i would add this as I feel it could work quite well for a percentage bar/visual level of something.
It also means you're not creating multiple divs if you don't have to, and keeps this page up-to-date
You can only use one color but as many images as you want, here is the format:
background: [ <bg-layer> , ]* <final-bg-layer>
<bg-layer> = <bg-image> || <bg-position> [ / <bg-size> ]? || <repeat-style> || <attachment> || <box>{1,2}
<final-bg-layer> = <bg-image> || <bg-position> [ / <bg-size> ]? || <repeat-style> || <attachment> || <box>{1,2} || <background-color>
or
background: url(image1.png) center bottom no-repeat, url(image2.png) left top no-repeat;
If you need more colors, make an image of a solid color and use it. I know it’s not what you want to hear, but I hope it helps.
The format is from http://www.css3.info/preview/multiple-backgrounds/
In case someone needs a CSS background with different color repeating horizontal stripes, here is how I managed to achieve this:
body {
font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 13px;
}
.css-stripes {
margin: 0 auto;
width: 200px;
padding: 100px;
text-align: center;
/* For browsers that do not support gradients */
background-color: #F691FF;
/* Safari 5.1 to 6.0 */
background: -webkit-repeating-linear-gradient(#F691FF, #EC72A8);
/* Opera 11.1 to 12.0 */
background: -o-repeating-linear-gradient(#F691FF, #EC72A8);
/* Firefox 3.6 to 15 */
background: -moz-repeating-linear-gradient(#F691FF, #EC72A8);
/* Standard syntax */
background-image: repeating-linear-gradient(to top, #F691FF, #EC72A8);
background-size: 1px 2px;
}
<div class="css-stripes">Hello World!</div>
JSfiddle

Resources