I've got an image, with properties defined as follows:
.icon {
background-color: white;
border-radius: 50%;
width: 50px;
height: 50px;
}
Due to the border-radius, the image is in a circle. Is there a way to tighten this circle by some number of pixels, such that some "outer layers" of the circle are shaved off, without scaling the image down with it?
A combination of background-size and background-position properties allow you to resize an image as a background relative to the element it is a background of. Sorry if that is a mouthful, in other words, if this is your initial approach:
.icon {
background-color: white;
border-radius: 50%;
width: 50px;
height: 50px;
}
<img src="https://barkpost-assets.s3.amazonaws.com/wp-content/uploads/2013/11/grumpy-dog-11.jpg" class="icon" />
Instead if the image is applied as a background image you can control the size relative to the element:
.icon {
background-color: white;
background-image: url('https://barkpost-assets.s3.amazonaws.com/wp-content/uploads/2013/11/grumpy-dog-11.jpg');
background-position: center center; /* two values for horizontal and vertical positioning, you can use px or other units to configure distance too. */
background-size: 180% 180%; /* also two values for height and width, here I am using greater than 100% to make the image larger than the element, achiving the effect you are looking for */
border-radius: 50%;
width: 50px;
height: 50px;
}
<div class="icon" role="img" aria-label="this puppy looks a little closer, right?"></div>
I can think of a few different ways to do this, depending on how "clean" you need this to be. Read the comments in-line for a description of what is going on.
/* Your code, as is: */
img {
background-color: white;
border-radius: 50%;
width: 150px;
height: 150px;
}
/* Using clip-path (not supported in IE/Edge): */
img.clipped {
clip-path: circle(28.6% at 50% 50%);
}
/* Using a background image: */
span.image {
width: 150px;
height: 150px;
display: inline-block;
background: url(https://via.placeholder.com/150);
border-radius: 50%;
box-shadow: inset 0px 0px 0px 25px #fff;
}
/* Using a span as a 'wrapper': */
span.image_wrapper {
width: 150px;
height: 150px;
display: inline-block;
border-radius: 50%;
box-shadow: inset 0px 0px 0px 25px #fff;
}
<!-- Your code, as is: -->
<img src="https://via.placeholder.com/150" />
<!-- Using clip-path (not supported in IE/Edge) -->
<img src="https://via.placeholder.com/150" class="clipped" />
<!-- Using a background image: -->
<span class="image"></span>
<!-- Using a span as a 'wrapper' -->
<span class="image_wrapper">
<img src="https://via.placeholder.com/150" class="clipped" />
</span>
For clip-path see: https://caniuse.com/#search=css%20clip
Related
I'm wondering if it is at all possible to achieve a curved border (with a stroke) using only CSS? At the moment I'm creating curved borders for the header of my website using images:
I'd like to change this to a CSS solution so that I'm not having to alter images when the amount of content within changes - I need these to be dynamic and responsive, I've managed to draw a curve using border-radius:
This works much better for me, but I'm wondering if it is possible to add a stroke to it to make it look a more like the image representation? Any help is greatly appreciated. Here's the code I've written to achieve this:
<div class="slider">
<div class="slide">
<!-- Content -->
</div>
</div>
CSS:
.slider {
background: #21639e;
}
.slider .slide {
background: url("image.jpg") no-repeat #21639e;
border-radius: 100%/0 0 30px 30px;
}
I did try adding border-bottom: 5px solid #fff; to the .slide class, but it ended up looking like this:
I've created a jsfiddle for you to test what I'm trying to achieve.
Yes, you can try and use box shadows to create this kind of border. Applying a white box shadow on the outer side of the element will make it look like a stroke/border.
This - border-bottom: 5px solid #fff; produces a different kind of effect because we are applying only the bottom border to the element. The borders on the left and right are non existent (zero width) and so the line thins out as you go nearer to the edges.
.slider {
height: 500px;
background: #21639e;
}
.slider .slide {
height: 200px;
background: url("http://placehold.it/800x800/FF00FF") no-repeat #21639e;
border-radius: 100%/0 0 30px 30px;
box-shadow: 0px 6px 0px white;
}
<div class="slider">
<div class="slide">
Some content
</div>
</div>
Below is an updated version of your Fiddle.
For a more graceful looking curve then you can also try the below approach. It uses a pseudo element which is wider than the .slide and then centers the image within it. (I feel that this approach makes it look closer to the original image but the choice is yours)
.slider {
height: 500px;
background: #21639e;
}
.slider .slide {
position: relative;
height: 200px;
width: 100%;
overflow: hidden;
}
.slider .slide:before {
position: absolute;
content: '';
left: -2%;
top: -6px;
width: 104%;
height: 100%;
background: url("http://placehold.it/800x800/FF00FF") no-repeat center center #21639e;
border-radius: 100%/0 0 30px 30px;
box-shadow: 0px 6px 0px white;
}
<div class="slider">
<div class="slide">
Some content
</div>
</div>
I was wondering if it is possible to make a square with round corners and a indented border in pure CSS.
Currently I have this:
#custom-square {
position: relative;
display: block;
width: 75px;
height: 75px;
border: 2px solid #8A6EF1;
border-radius: 10px;
background-color: white;
}
Considering the hassle and amount of code needed to align double curves with CSS, SVG seems way more appropriate. A few other reasons to go for svg here are :
control of the path (color, width, curve...)
control the fill with a plain color, gradient or image
less code
you can display it over a non plain background (gradient or image)
maintain the boundaries of the shape for user interactions (hover, click...)
Here is a basic example using an inline svg with a path element.
The curves are drawn with Cubic Bezier curves :
svg{width:30%;}
<svg viewbox="0 0 10 10">
<path d="M1.5 0.5 Q5 1 8.5 0.5 Q9.5 0.5 9.5 1.5 Q9 5 9.5 8.5 Q9.5 9.5 8.5 9.5 Q5 9 1.5 9.5 Q0.5 9.5 0.5 8.5 Q1 5 0.5 1.5 Q0.5 0.5 1.5 0.5z"
fill="none" stroke-width="0.2" stroke="#8A6FF2" />
</svg>
Another pure CSS approach for creating this border would be to make use of border-image property. All that is required is create an image with the required border shape and set it to an element using the border-image-source property.
.shape.large {
height: 300px;
width: 300px;
border-image-source: url(http://i.stack.imgur.com/Qkh6A.png);
border-image-width: 34px; /* the width of the border portions in the image - refer to image at the end of the answer for the exact portion details*/
border-image-slice: 34; /* equal to border-image-width */
border-width: 34px; /* equal to border-image-width */
}
.shape.small {
height: 100px;
width: 100px;
border-image-source: url(http://i.stack.imgur.com/Mra4B.png);
border-image-width: 14px;
border-image-slice: 14;
border-width: 14px;
}
.shape.small.fill {
background: aliceblue content-box;
border-image-source: url(http://i.stack.imgur.com/Ovj03.png);
border-width: 14px;
}
/* Just for demo */
body {
background: url(http://lorempixel.com/800/800/abstract/2);
}
.shape.small {
float: left;
}
.shape.large {
clear: both;
}
<div class='shape small'>Some content</div>
<div class='shape small fill'>Some content</div>
<div class='shape large'>Some content</div>
At present this method is definitely not much advantageous compared to SVG but it is an option and in my opinion is better than the other CSS only approaches that are possible.
The advantages of this approach are:
Very minimal and low complexity code.
Better control over the curves and their radii (like with SVG) because the image with the required border curvature can be created separately.
Can be placed on top of an image or a gradient background.
Can be made to degrade gracefully (into a solid square border) in browser's that don't support it.
The drawbacks are:
The container is still a square and so hover effects will not be restricted to the boundaries of the shape unlike with SVG.
Adding solid color fill to the shape is possible (by using a filled version of the image) but adding a gradient or image fill is tricky because borders are still blocks (that is, there are transparent areas on either side of the curves).
The output is responsive but as dimensions increase or decrease beyond a threshold, the shape starts to look a bit compressed or stretched. So, this is more suited for break-point based design.
The browser support is not bad but is not great either. It works in Chrome, Firefox, Safari, Opera and IE11+.
Calculation of Border Image Width:
The width or height of border area (which becomes the border-image-width) is nothing but the width of the portion highlighted in the below image.
This draft mock up is as close as i could get it to pure CSS, but still requires a nested div. You would need to tweak the sizing / radius for the before / after circles.
Pen
div {
position: absolute;
top: 100px;
left: 100px;
width: 100px;
height: 100px;
border: 4px solid purple;
border-radius: 30px;
//overflow: hidden;
box-sizing: border-box;
&:before {
position: absolute;
top: -4px;
left: -94px;
content: ' ';
width: 100px;
height: 100px;
border: 4px solid purple;
border-radius: 50px;
box-sizing: border-box;
background-color: white;
clip: rect(0px, 100px, 100px, 90px);
}
&:after {
position: absolute;
top: -4px;
right: -94px;
content: ' ';
width: 100px;
height: 100px;
border: 4px solid purple;
border-radius: 50px;
box-sizing: border-box;
background-color: white;
clip: rect(0px, 10px, 100px, 0px);
}
}
div > div {
position: absolute;
top: -4px;
left: -4px;
transform: rotate(90deg);
border-color: transparent;
}
SVG is probably the way to go here, but here's a pretty close approximation in pure CSS. It could be made even better by increasing the size of the outer circles.
#middle {
width: 96px;
height: 96px;
border-radius: 10px;
background-color: green;
border: 2px solid #8A6EF1;
}
.outside {
width: 100px;
height: 100px;
position: relative;
overflow: hidden;
margin: 0;
padding: 0;
}
.cutout {
width: 96px;
height: 96px;
border-radius: 50%;
background-color: white;
border: 2px solid #8A6EF1;
}
#top {
top: -100px;
height: 10px;
}
#right {
top: -110px;
left: 90px;
width: 10px;
}
#bottom {
top: -120px;
height: 10px;
}
#left {
top: -220px;
width: 10px;
}
#top > .cutout {
margin-top: -90px;
}
#left > .cutout {
margin-left: -90px;
}
<div id="wrapper">
<div id="middle">
</div>
<div id="top" class="outside">
<div class="cutout">
</div>
</div>
<div id="right" class="outside">
<div class="cutout">
</div>
</div>
<div id="bottom" class="outside">
<div class="cutout">
</div>
</div>
<div id="left" class="outside">
<div class="cutout">
</div>
</div>
</div>
I've tried the perspective solution here How to transform each side of a shape separately? but can't get it to work probably due to the irregularness of the shape. Only the top and right side columns are slanted, vertical and bottom are straight. How can I do this with CSS?
Using CSS borders you can create triangles and trapezoids.
You can achieve your shape joining a triangle and a trapezoid.
.triangle {
border: 0 solid red;
border-left-width: 500px;
border-top-width: 30px;
border-top-color: transparent;
}
.trapezoid {
border: 0 solid red;
width: 500px;
border-bottom-width: 150px;
border-right-width: 30px;
border-right-color: transparent;
}
<div class="triangle"></div>
<div class="trapezoid"></div>
Method 1: Clip path
You could make use of CSS clip-path feature to clip a rectangle into the required polygon shape.
div {
box-sizing: border-box;
height: 150px;
width: 250px;
background: red;
padding: 10px;
-webkit-clip-path: polygon(0% 0%, 90% 10%, 100% 100%, 0% 100%);
clip-path: polygon(0% 0%, 90% 10%, 100% 100%, 0% 100%);
}
div#image {
background: url(http://lorempixel.com/400/200);
}
/* Just for demo */
div{
float: left;
margin: 10px;
transition: all 1s;
}
div:hover{
height: 200px;
width: 300px;
}
<div>Some text</div>
<div id="image"></div>
Pros:
Supports non-solid color fills inside the shape and also allow text to be present inside.
The shape is responsive and can adapt even if the container's dimensions change.
Cons:
Poor browser support for the CSS clip-path feature. This can be overcome by using inline SVG for the clip-path like in the below snippet as this has much better browser support.
div {
box-sizing: border-box;
height: 150px;
width: 250px;
padding: 10px;
background: red;
-webkit-clip-path: url(#clip);
clip-path: url(#clip);
}
div#image {
background: url(http://lorempixel.com/400/200);
}
/* Just for demo */
div{
float: left;
margin: 10px;
transition: all 1s;
}
div:hover{
height: 200px;
width: 300px;
}
<svg width="0" height="0">
<defs>
<clipPath id="clip" clipPathUnits="objectBoundingBox">
<path d="M0 0, 0.9 0.1, 1 1, 0 1z" />
</clipPath>
</defs>
</svg>
<div>
Some text
</div>
<div id="image"></div>
Method 2: CSS Transforms
Generally it is better not to use transforms when there is going to be content like image or text inside the shape (or) when the shape's background is not going to be a solid color because then we would either have to (a) reverse transform the child elements separately to make them look normal or (b) use absolute positioning.
For this particular shape, having text inside the shape is not a problem even while using transforms but having non solid background colors would be.
Option 1: Using two pseudo-elements
You could use a couple of pseudo-elements with skew transforms, position one on the top and the other on the right to produce the required shape. Hover the shape in snippet to see how it is created.
div {
position: relative;
height: 150px;
width: 250px;
background: red;
margin: 40px 40px 0px 0px;
}
div:after,
div:before {
position: absolute;
content: '';
background: red;
z-index: -1;
backface-visibility: hidden;
}
div:before {
height: 12.5%;
width: 100%;
top: 0px;
left: 0px;
transform-origin: right top;
transform: skewY(3deg);
}
div:after {
height: 100%;
width: 12.5%;
right: -1px;
top: -1px;
transform-origin: right top;
transform: skewX(10deg);
}
/* Just for demo */
div{
transition: all 1s;
}
div:hover{
height: 250px;
width: 300px;
}
div:hover:after{
background: blue;
}
div:hover:before{
background: green;
}
<div>Some text</div>
Pros:
Shape can be created with a single element and can have text inside it without any trouble.
Cons:
Having gradients (or) images as background for the shape is complex because they would need reverse rotation as mentioned earlier.
Shape is not 100% scalable as dimensions of the container should change proportionately for the shape to be maintained (hover on the shape in the snippet to see what I mean). Reason is same as mentioned here.
Option 2: Using one pseudo-element
This is pretty similar to the previous option except that this uses a single pseudo-element along with a overflow: hidden on the parent.
div {
position: relative;
box-sizing: border-box;
height: 200px;
width: 300px;
padding: 10px;
overflow: hidden;
}
div:after {
position: absolute;
content: '';
top: 0px;
left: -20px;
height: 100%;
width: 100%;
background: red;
transform-origin: left bottom;
transform: skewY(5deg) skewX(7.5deg);
z-index: -1;
}
div:hover {
height: 300px;
width: 500px;
transition: all 1s;
}
<div>Some text</div>
Pros:
Shape can be created with a single element and can have text inside it without any trouble.
Shape is responsive and can adapt even if the container's dimensions change .
Cons:
Same constraint as the previous option for gradient and image backgrounds.
Not suitable if the overflow: hidden on the parent is a constraint.
A solution is:
div {
width: 300px;
height: 100px;
margin:50px;
background-color: yellow;
border: 1px solid black;
}
.thisdiv {
-ms-transform: skewX(-20deg); /* IE 9 */
-webkit-transform: skewX(-20deg); /* Safari */
transform: skewX(-20deg); /* Standard syntax */
}
<div class="thisdiv">
This is the div I will skew
</div>
This is how to skew an element, if you want to make the shape you added, try using two overlaping div's, position, scale, rotate and skew, like this:
.outer-div{
position:relative;
margin:50px;
width:200px;
height:200px;
border:2px black dashed;
}
.inner-one{
position:absolute;
left:0;
bottom:0;
width:180px;
height:180px;
background:red;
}
.inner-two{
position:absolute;
bottom:2px;
right:0px;
width:200px;
height:195px;
background:red;
transform: rotate(7deg) skew(14deg) scale(0.905); /* Standard syntax */
}
<div class="outer-div">
<div class="inner-one">
</div>
<div class="inner-two">
</div>
</div>
2 Triangle Solution for Irregular Quadrilateral in CSS
In looking at your image, I notice that the skew at the top and right are really just long, narrow triangles overlaying the rectangle.
So what I did was create triangles using CSS border properties and absolutely position them over the rectangle.
#rectangle {
width: 400px;
height: 200px;
background-color: red;
margin-top: 25px;
position: relative;
}
#triangle-down {
border-left: 30px solid red;
border-right: 0;
border-top: 200px solid transparent;
position: absolute;
right: -30px;
top: 0;
}
#triangle-left {
border-top: 0;
border-bottom: 15px solid red;
border-right: 400px solid transparent;
position: absolute;
right: 0;
top: -15px;
}
<div id="rectangle">
<div id="triangle-down"></div>
<div id="triangle-left"></div>
</div>
jsFiddle demo
You could check out the clip-path property (see below from MDN), but support is very patchy. Chrome 24+ supports with prefix and FF, but only URL values, which reference a path in an SVG. You can read more about clip-path here.
Here's a basic pen - this will only work in Chrome.
From MDN
The clip-path CSS property prevents a portion of an element from getting displayed by defining a clipping region to be displayed i.e, only a specific region of the element is displayed. The clipping region is a path specified as a URL referencing an inline or external SVG, or shape method such as circle(). The clip-path property replaces the now deprecated clip property.
developer.mozilla.org/en-US/docs/Web/CSS/clip-path (sorry, not enough rep to link)
I have just started working with CSS.
I have a rectangle image. I want to put it on a background and view it as a circle with light transparency as the example.
Is this what you looking for?
When you apply: border-radius: 50%; to your img it gets a circle as you you want.
.bg {
background-color: mediumaquamarine;
width: 500px;
height: 500px;
margin: auto
}
img {
border-radius: 50%;
/* Safari 3-4, iOS 1-3.2, Android 1.6- */
-webkit-border-radius: 50%;
/* Firefox 1-3.6 */
-moz-border-radius: 50%;
border: 1px solid red;
margin-left: 25%;
margin-top: 25%;
z-index: 1;
position: relative;
opacity: 0.8
}
<div class="bg">
<img src="http://placehold.it/250x250&text=Image" />
</div>
here's a rough demo of how to do it:
http://jsfiddle.net/jalbertbowdenii/vfac6L4x/
using your pix, just simply add the correct url for the img element and change the backgroudn color of the mask container div as well as the border color of the image.
if you want more info, search for css masks
because stackoverflow requires this:
.mask{background-color:#000}
img{display:block; margin-left:auto; margin-right:auto;
border-radius:25px; border:solid #000}
and the markup
<div class="mask">
<img src="https://photos-6.dropbox.com/t/1/AAASULb1odiWJlk3dyEG-rF4B0baCCQ2D9aoTqXZiYZW6w/12/107220852/jpeg/1024x768/3/1416250800/0/2/trans-cirecle.jpg/VFul9uUE7QKOIrYKVNy58z9JzoOHj9UK3AGRUsSFbgY" />
</div>
Add border-radius:50% to the image; img{}
Change values of border-radius to various pixel values and percentage values to get more effects.
I have this HTML:
<div id="graphic">lorem ipsum</div>
with this CSS:
#graphic { background-image: url(image.jpg); width: 200px; height: 100px;}
The background image I'm applying is 200x100 px, but I only want to display a cropped portion of the background image of 200x50 px.
background-clip does not appear to be the right CSS property for this. What can I use instead?
background-position should not be used, because I'm using the above CSS in a sprite context where the image part I want to show is smaller than the element on which the CSS is defined.
You can put the graphic in a pseudo-element with its own dimensional context:
#graphic {
position: relative;
width: 200px;
height: 100px;
}
#graphic::before {
position: absolute;
content: '';
z-index: -1;
width: 200px;
height: 50px;
background-image: url(image.jpg);
}
#graphic {
width: 200px;
height: 100px;
position: relative;
}
#graphic::before {
content: '';
position: absolute;
width: 200px;
height: 50px;
z-index: -1;
background-image: url(http://placehold.it/500x500/); /* Image is 500px by 500px, but only 200px by 50px is showing. */
}
<div id="graphic">lorem ipsum</div>
Browser support is good, but if you need to support IE8, use a single colon :before. IE has no support for either syntax in versions prior to that.
may be you can write like this:
#graphic {
background-image: url(image.jpg);
background-position: 0 -50px;
width: 200px;
height: 100px;
}
Another option is to use linear-gradient() to cover up the edges of your image. Note that this is a stupid solution, so I'm not going to put much effort into explaining it...
.flair {
min-width: 50px; /* width larger than sprite */
text-indent: 60px;
height: 25px;
display: inline-block;
background:
linear-gradient(#F00, #F00) 50px 0/999px 1px repeat-y,
url('https://championmains.github.io/dynamicflairs/riven/spritesheet.png') #F00;
}
.flair-classic {
background-position: 50px 0, 0 -25px;
}
.flair-r2 {
background-position: 50px 0, -50px -175px;
}
.flair-smite {
text-indent: 35px;
background-position: 25px 0, -50px -25px;
}
<img src="https://championmains.github.io/dynamicflairs/riven/spritesheet.png" alt="spritesheet" /><br />
<br />
<span class="flair flair-classic">classic sprite</span><br /><br />
<span class="flair flair-r2">r2 sprite</span><br /><br />
<span class="flair flair-smite">smite sprite</span><br /><br />
I'm using this method on this page: https://championmains.github.io/dynamicflairs/riven/ and can't use ::before or ::after elements because I'm already using them for another hack.