Radial gradient center doesn't match span center - css

I centered radial gradient 200 px from the top and 200 px from the left. The same I did with span witch contains letter "a". But as I see, gradient center doesn't mach the span center.
Why does it happen?
<body>
<div class="box"><span>a</span></div>
</body>
CSS
.box {
position:relative;
width: 300px;
height: 300px;
background: -webkit-gradient(radial, 200 200, 20, 200 200, 30, from(#FCFCFC), to(#CF0C13));
}
span {
position: absolute;
left: 200px;
top: 200px;
}

You have it correct.
Problem:
The problem you are seeing is because, the span starts at X = 200px and Y = 200px. While the radial gradient sets its center at that point. This is because of the default font glyph which leaves space for ascenders and descenders. This will change for every font-family you have.
This is visible in this snippet, see the span marked in blue:
.box {
position: relative;
width: 300px; height: 300px;
background: -webkit-radial-gradient(200px 200px, circle, #fcfcfc 10%, #cf0c13 15%, #cf0c13 100%);
}
span {
position: absolute;
left: 200px; top: 200px;
border: 1px solid blue;
}
<div class="box"><span>a</span></div>
Solution:
Just shift the radial origin by 10px down on Y axis.
Like this: -webkit-radial-gradient(200px 210px....
Snippet:
.box {
position: relative;
width: 300px; height: 300px;
background: -webkit-radial-gradient(200px 210px, circle, #fcfcfc 10%, #cf0c13 15%, #cf0c13 100%);
}
span {
position: absolute;
left: 200px; top: 200px;
}
<div class="box"><span>a</span></div>
Alternatively, if your span contents are going to change, then its better to use the translate(-50%, -50%) trick to shift it negatively by half-of its size.

In gradient definition you tell where should be the center of gradient background. In left/top properties for span you set left top corner of this span.
It means that the gradient center is in the same place as a span's left top corner (You can see that on http://jsfiddle.net/cyzczvd1/4/).
You need to move span a little bit, I prepare you another fiddle:
.box {
position:relative;
width: 300px;
height: 300px;
background: -webkit-gradient(radial, 200 200, 20, 200 200, 30, from(#FCFCFC), to(#CF0C13));
}
span {
position: absolute;
left: 200px;
top: 200px;
/*
added lines below, background to see element borders, size, centering of text and
move back - you can set directly left: 180px; top: 180px; and avoid this negative margins
*/
background: red;
display: block;
width: 40px;
height: 40px;
margin: -20px 0 0 -20px;
text-align: center;
line-height: 40px;
}
http://jsfiddle.net/cyzczvd1/3/

You need to use transform: translate(-50%, -50%) on the span to align it in the center. This way you won't have to worry about the font-size.
.box {
position: relative;
width: 300px;
height: 300px;
background: -webkit-gradient(radial, 200 200, 20, 200 200, 30, from(#FCFCFC), to(#CF0C13));
}
span {
position: absolute;
left: 200px;
top: 200px;
font-size: 16px;
transform: translate(-50%, -50%);
}
<div class="box"><span>a</span>
</div>
For the radial-gradient, you should use the following syntax.
background: -webkit-radial-gradient(200px 200px, #FCFCFC 20px, #CF0C13 30px);
background: -moz-radial-gradient(200px 200px, #FCFCFC 20px, #CF0C13 30px);
background: radial-gradient(200px 200px, #FCFCFC 20px, #CF0C13 30px);

Related

Box-shadow not replicating perfect circle

I'm using the box shadow property to replicate the original circle multiple times, with different spread each shadow, see:
.a {
width: 50px;
height: 50px;
background: #EEB850;
border-radius: 50%;
position: relative;
top: 117;
left: 167;
box-shadow: 0 0 0 50px #243D83,
0 0 0 100px #6592CF;
}
However, the shadows are not replicating the circle, but instead, they look like squares with rounded corners. Any suggestion about this? Screenshot of the result.
While there is the bug in Edge/Chrome a workaround might be to create the circles with radial-gradients on a larger before pseudo element.
Here's a simple example:
.a {
width: 50px;
height: 50px;
background: #EEB850;
border-radius: 50%;
position: relative;
top: 117px;
left: 167px;
}
.a::before {
content: '';
position: absolute;
display: inline-block;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 400%;
height: 400%;
border-radius: 50%;
background-image: radial-gradient(#EEB850 0 25px, #243D83 25px 50px, #6592CF 50px 75px, transparent 75px 100%);
background-position: top left;
}
<div class="a"></div>
Note: because one can sometimes get ragged effects with radial gradient the snippet has put the central color as its first circle to avoid edge effects (small gaps between the element and the radial gradient).

Is it possible to cut specific parts of an image?

Sometimes images just explain things better than 1000 words
assumed the black border is my image I want to cut off the top left/right edge - like marked by the red lines.
Would it be possible (if yes: how) to cut an image this way with CSS?
Just in case its not clear what I mean by cut: I want
By cut I mean, that the image will look like this
Without using a wrapper element, you can use clip-path, though the support isn't great.
img.cut {
-webkit-clip-path: polygon(50px 0, calc(100% - 50px) 0, 100% 50px, 100% 100%, 0 100%, 0 50px);
clip-path: polygon(50px 0, calc(100% - 50px) 0, 100% 50px, 100% 100%, 0 100%, 0 50px);
}
<img class="cut" src="http://lorempixel.com/200/300/">
This uses calc (widely supported), so you can specify exact pixel values to clip by.
CSS Pseudo
If you know you're background is going to remain a solid colour, you can achieve this using pseudo elements in a number of ways.
1st option
A very simple solution is to use the pseudo elements with borders to which should get you the effect you want.
div {
height: 300px;
background: red;
position: relative;
}
div:before {
content: '';
position: absolute;
top: 0;
left: 0;
border-top: 80px solid white;
border-right: 80px solid red;
width: 0;
}
div:after {
content: '';
position: absolute;
top: 0;
right: 0;
border-top: 80px solid white;
border-left: 80px solid red;
width: 0;
}
<div></div>
2nd Option
Using a single pseudo element which is larger than the parent and rotating it to get the desired effect.
This is a much cleaner effect and also means the use of background images is supported and easier to implement.
div {
height: 200px;
width: 200px;
background: transparent;
position: relative;
z-index: 9;
overflow: hidden;
}
div:before {
content: '';
width: 200%;
height: 200%;
position: absolute;
transform: rotate(45deg);
background: red;
left: -50%;
top: 20px;
<div></div>

Top and Bottom bent borders

I'm looking for a way to create bent top and bottom borders like the div in this image. I've tried some ways mentioned here but it depends on using white divs with border-radius on top of the main div but as you can see in this image it should be transparent to display the background image.
This is possible using svg.
For responsiveness remove the svg's width and height attributes, add viewBox="0 0 400 150" then try changing #image's width and height, the svg will respond to its width and height.
Demo on Fiddle demonstrating responsive shape.
Browser support for this approach - This will work on all browsers but IE8.
body {
background: teal;
}
#image {
width: 600px;
height: 300px;
position: relative;
background: url(http://lorempixel.com/600/300);
}
svg {
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
<div id="image">
<svg width="400" height="150">
<path opacity="0.6" fill="red" d="M0,10 Q0,0 10,0 Q195,40 390,0 Q400,0 400,10 Q390,75 400,140 Q400,150 390,150 Q195,100 10,150 Q0,150 0,140 Q10,75 0,10" />
</svg>
</div>
Another posibility, not using clipping but multiple backgrounds.
Technically less advanced than chipChocolate answer, just providing an alternative
.test {
position: absolute;
left: 50px;
top: 50px;
width: 400px;
height: 100px;
border-radius: 10px;
background-image: radial-gradient(circle at center -778px,
transparent 800px, rgba(255,0,0,0.4) 800px),
radial-gradient(circle at center 828px,
transparent 800px, rgba(255,0,0,0.4) 800px);
background-position: center top, center bottom;
background-size: 100% 50%, 100% 50%;
background-repeat: no-repeat;
}
Thw idea is to divide the element in 2 halves, and then set in each a radial gradient that matches the corners position. The final posiotion of the gradients adjusted by hand.
Can de done responsively also.
demo
body {
width: 100%;
height: 100%;
background: url(http://placekitten.com/g/600/300);
}
.test {
position: absolute;
left: 50px;
top: 50px;
width: 400px;
height: 100px;
border-radius: 10px;
background-image: radial-gradient(circle at center -778px,
transparent 800px, rgba(255,0,0,0.4) 801px),
radial-gradient(circle at center 828px,
transparent 800px, rgba(255,0,0,0.4) 801px);
background-position: center top, center bottom;
background-size: 100% 50%, 100% 50%;
background-repeat: no-repeat;
}
<div class="test"></div>
An other approach with one div, 2 pseudo elements , border-radius and box-shadows :
div {
width: 70%; height: 150px;
margin: 20px auto;
position: relative;
border-radius: 10px;
overflow: hidden;
opacity: 0.5;
}
div:before,div:after {
content: '';
position: absolute;
height: 100%; width: 300%;
left: -100%;
border-radius: 100%;
box-shadow: 0px 0px 0px 140px red;
}
div:before {top: -146px;}
div:after {bottom: -146px;}
body {background: url('http://lorempixel.com/output/people-q-c-640-480-1.jpg');background-size: cover;}
<div></div>
Actually doing this using the CSS would almost be impossible, and you would be good if you just try out a simple PNG image, created using Photoshop, Google Images etc, and create the image exactly of this size and then use it inside the website.
You can add the transparency to the image while creating it by using the Adobe UI tools for editing the image, or you can use the alpha filter in CSS to set the transparency effect to it to display the element that is residing behind it (the effect that you want).

Make an arrow shape with responsive width and only CSS

I'm trying to make a container that has an upward arrow attached to it. I am familiar with the border drawing trick and think that's a likely solution, but it only works for known sizes I think, since you have to specify border in em or px.
The shape I would like to make is this:
.
/ \
/ \
/ \
| flex |
| |
Where the content area can flex to different sizes as a percentage of a parent container.
Here is the CSS, with the problem area flagged:
.metric {
display: inline-block;
position: relative;
height: 150px;
width: 50%;
background: lawngreen;
}
.metric:after {
position: absolute;
top: -25px;
left: 0;
content: '';
background: white;
width: 100%;
height: 0;
border: 75px solid white; /* this fixed width is the problem */
border-top: none;
border-bottom: 25px solid lawngreen;
box-sizing: border-box;
}
Here is the jsfiddle: http://jsfiddle.net/C8XJW/2/
Do you guys know any way to pull this off?
Here is another posibility.
This one does the trick with gradient backgrounds. You need 2 of them, so that the diagonal is easily achieved:
Relevant CSS:
.metric:before, .metric:after {
position: absolute;
top: -25px;
content: '';
width: 50%;
height: 25px;
}
.metric:before {
left: 0px;
background: linear-gradient(to right bottom, transparent 50%, lawngreen 50%);
}
.metric:after {
right: 0px;
background: linear-gradient(to left bottom, transparent 50%, lawngreen 50%);
}
Updated Fiddle
The differences with Simple As Could Be solution:
Pro Transparent corners (relevant if you have a background)
Con Worse browser support
Here's one great solution. Bascially, you make the arrow always centered, and bigger than you'd ever need it, but lop off the overflow.
Here's the JSFiddle:
http://jsfiddle.net/nBAK9/4/
And here's the interesting code:
.metric:after {
position: absolute;
top: 0;
left: 50%;
margin-left: -250px; /* max expected width /2 */
content: '';
background: white;
width: 500px; /* max expected width */
height: 0;
border: 250px solid white; /* max expected width /2 */
border-top: none;
border-bottom: 50px solid #cf6; /* This size adjusts the slope of the triangle */
box-sizing: border-box;
}
Not sure you can, I played with it found that since em inherits from parents you can play a bit with it.
body{
font-size: 3em;
}
div {
width: 0;
height: 0;
border-style: solid;
border-width: 0 3em 4em 7em;
border-color: transparent transparent #007bff transparent;
-webkit-transform:rotate(360deg)
}
Fiddle
.top-arrow:before, .top-arrow:after {
position: absolute;
top: -25px;
content: '';
width: 50%;
height: 25px;
}
.top-arrow:before {
left: 0px;
background: linear-gradient(to right bottom, transparent 50%, black 50%);
}
.top-arrow:after {
right: 0px;
background: linear-gradient(to left bottom, transparent 50%, black 50%);
}
<div class="top-arrow"></div>

Part of div transparent?

Is it possible to make only part of div transparent like an amount of space in div.
For example, you select 100px from top of div and the top 100px have an opacity set?
How would I do it?
You can do a couple of things:
Try a background image where half is transparent and the other half is not.
Use a CSS gradient in such a way that half is transparent and the other is not. Ex:
background: -moz-linear-gradient(top, rgba(30,87,153,0) 0%, rgba(41,137,216,0) 50%, rgba(34,125,203,1) 52%, rgba(125,185,232,1) 100%); /* FF3.6+ */
Use multiple divs where one has transparent BG and the other does not. Ex:
<div>
<div id="transparent" style="background: transparent"></div>
<div id="not-transparent" style="background: #000"></div>
</div>
I'm sure there are other ways, but those are the first three that come to mind.
Good luck.
Either you create the right background-image using a semi-transparent PNG (transparent at top, opaque at bottom for example) ; either you use two sub-divs, each having its own background-color (one of which with rgba for the transparent part).
You can use css3 properties along with pseudo elements to create this effect:
The trick is to draw a box with :before or :after pseudo element. We can apply background property for inner semi-transparent background. While for outer background we can use a large box-shadow value.
HTML:
<div class="box"></div>
CSS:
.box {
position: relative;
overflow: hidden;
height: 120px;
width: 250px;
}
.box:before {
background: rgba(0, 0, 0, 0.3);
box-shadow: 0 0 0 1000px #000;
position: absolute;
height: 50px;
width: 50px;
content: '';
left: 0;
top: 0;
}
html,
body {
height: 100%;
}
body {
background: linear-gradient(to top, #ff5a00 0, #ffae00 100%);
margin: 0;
}
.box {
position: relative;
margin: 30px 20px;
overflow: hidden;
height: 120px;
width: 250px;
}
.box:before {
background: rgba(0, 0, 0, 0.3);
box-shadow: 0 0 0 1000px #000;
position: absolute;
height: 50px;
width: 50px;
content: '';
left: 0;
top: 0;
}
<div class="box"></div>

Resources