Scale border on svg without viewbox - html

I have 2 svgs one has viewbox and the other doesn't. Both are 100% width of the parent. The first one scales with the viewbox and the second scales with the height of the parent, because I have a hover height transition.
The problem is that I want both to have the same stroke-width. I want the stroke to scale like it scales with the svg that has viewbox, but the stroke of the second rect always stays 2px.
How can I keep the functionality of scaling the height of the rect with it's parent, but also to have the same border width as the first svg?
body > div{
width: 100px;
height: 400px;
}
svg{
width: 100%;
stroke-width: 2px;
stroke: black;
}
.svg-with-viewbox rect{
fill: red;
}
div > div{
height: 50px;
width: 100%;
transition: 1.5s all;
}
div > div:hover{
height: 200px;
}
.scale-height{
fill: yellow;
height: 100%;
}
<div>
<svg class="svg-with-viewbox" viewbox="0 0 20 20">
<rect height="20" width="20"/>
</svg>
<div>
<svg class="scale-height">
<rect width="100%" height="100%">
</rect>
</svg>
</div>
</div>

You could use a drop-shadow() filter , so no matter if the svg part is rescaled, it will remain the same size around the transparent edges.
example
body>div {
width: 100px;
height: 400px;
}
svg {
width: 100%;
filter: /* on on each sides */
drop-shadow( 2px 0 black)
drop-shadow(-2px 0 black)
drop-shadow( 0 2px black)
drop-shadow( 0 -2px black);
margin: 2px;/* increase margin or padding to include the drop-shadow */
}
.svg-with-viewbox rect {
fill: red;
}
div>div {
height: 50px;
width: 100%;
transition: 1.5s all;
}
div>div:hover {
height: 200px;
}
.scale-height {
fill: yellow;
height: 100%;
}
<div>
<svg class="svg-with-viewbox" viewbox="0 0 20 20">
<rect height="20" width="20"/>
</svg>
<div>
<svg class="scale-height">
<rect width="100%" height="100%">
</rect>
</svg>
</div>
</div>

Related

clipPath cut off by container

So I am pretty close to my desired effect, the issue though is that the clipPath I am using while rotating gets cut off by the container. Is there a way to remedy this? I tried messing with the viewBox and other properties but to no avail. I am not super well versed in using clipPath. Would using CSS clip-path be a better call and just rotate a pseudo element the opposite way?
.red {
background-image: url('https://cdn.mos.cms.futurecdn.net/u8wSHMmMMXzZuAFBCmcsCK-650-80.jpg');
background-size: 90%;
height: 100vh;
width: 700px;
clip-path: url(#clipPolygon);
position: relative;
z-index: 2;
margin-top: 120px;
margin-left: 250px;
}
.bg {
position: absolute;
top: 0;
left: 0;
z-index: 1;
}
svg {
}
defs {
transition: all 5s;
transform: rotate(360deg);
}
<div class="red">
<svg>
<defs>
<clipPath id="clipPolygon">
<polygon points="200 250,400 100,300 50,0 0">
<animateTransform attributeName="transform" begin="0s" dur="2.5s" type="rotate" from="360 160 160" to="0 160 160" repeatCount="indefinite"/>
</polygon>
</clipPath>
</defs>
</svg>
</div>
<div class="bg">
<img src="https://www.mcgilvraydesign.com/img/bgdemo3.jpg" alt="">
</div>
You can use your polygon as a CSS mask then you can easily handle the rotation using two elements rotating in opposite direction
.red {
background:url(https://www.mcgilvraydesign.com/img/bgdemo3.jpg) center/contain no-repeat;
min-height:350px;
height: 100vh;
overflow:hidden;
}
.red > div {
/* control the mask here */
-webkit-mask:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0 400 300"><polygon points="200 250,400 100,300 50,0 0"/></svg>')
center/ /* position */
300px 200px /* size */
no-repeat;
mask:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0 400 300"><polygon points="200 250,400 100,300 50,0 0"/></svg>')
center/
300px 200px
no-repeat;
height:100%;
position:relative;
animation:rotate 2s linear infinite;
}
.red > div::before {
content:"";
position:absolute;
/*big values here to avoid the cut effet*/
top:-100%;
left:-100%;
right:-100%;
bottom:-100%;
/* */
/* Control the skull here */
background: url('https://cdn.mos.cms.futurecdn.net/u8wSHMmMMXzZuAFBCmcsCK-650-80.jpg')
50% 45%/ /* position */
22% auto /* size*/
no-repeat,
#fff;
animation:inherit;
animation-direction:reverse;
}
#keyframes rotate {
to {
transform:rotate(-360deg);
}
}
body {
margin:0;
}
<div class="red">
<div></div>
</div>

How to add a transparent border? [duplicate]

This question already has an answer here:
How to cut a circular part from an image?
(1 answer)
Closed 3 years ago.
I have a simple user profile image, and a green state indicator.
I want to add a transparent border to the indicator, which surpasses the image in the background, like the image below.
It's easy when the background is a single color, I just have to add a border with the same color, but what to do when the background is a gradient or an image for example? If I add a white border, it looks like the image in the middle, and I would like to have a render like the right image.
How to achieve that ?
.user {
display: inline-block;
position: relative;
}
img {
width: 75px;
height: 75px;
border-radius: 75px;
}
.user-state {
position: absolute;
top: 4px;
right: 4px;
width: 15px;
height: 15px;
border-radius: 10px;
background: #57d642;
}
<body>
<div class="user">
<img src="http://lorempicsum.com/up/255/200/5" alt="">
<div class="user-state"></div>
</div>
</body>
I would consider SVG and mask like below:
.user {
display: inline-block;
position: relative;
}
svg {
width: 200px;
height: 200px;
}
.user:after {
content: "";
position: absolute;
top: 18px;
right: 18px;
width: 40px;
height: 40px;
border-radius: 50%;
background: #57d642;
}
body {
background: linear-gradient(to right, pink, purple);
}
<div class="user">
<svg viewbox="0 0 200 200">
<defs>
<mask id="hole">
<rect width="100%" height="100%" fill="white"/>
<!-- This circle is your hole on the top -->
<circle r="28" cx="162" cy="38" fill="black"/>
</mask>
<!-- the clipath will replace border-radius -->
<clipPath id="circle">
<circle cx="100" cy="100" r="100" fill="white" />
</clipPath>
</defs>
<image width="200" height="200" xlink:href="https://picsum.photos/id/1003/200/200" mask="url(#hole)" clip-path="url(#circle)"/>
</svg>
</div>
Border: ?px
Border-color: rgba(255,255,255,0)

How to create a rounded rectangle shape Css?

I'm trying to design a profile image shape just like this
but my code given me the following design
I'm worried about the white space inside the border and the shape here is code
.doctor-profile-photo {
width: 210px;
height: 210px;
border-radius: 60px/140px;
border: 5px solid #000;
box-shadow: 0px 2px 5px #ccc;
}
.doctor-profile-photo img {
width: 100%;
height: 100%;
border-radius: 60px/140px;
}
<div class="doctor-profile-photo">
<img src="http://weknowyourdreams.com/images/bird/bird-09.jpg" alt="">
</div>
This gives pretty similar output to what you want. Try tweaking the values of border-radius and height-width to achieve exactly what you want.
<style>
#pic {
position: relative;
width: 130px;
height: 150px;
margin: 20px 0;
background: red;
border-radius: 50% / 10%;
color: white;
text-align: center;
text-indent: .1em;
}
#pic:before {
content: '';
position: absolute;
top: 10%;
bottom: 10%;
right: -5%;
left: -5%;
background: inherit;
border-radius: 5% / 50%;
}
</style>
<div id="pic"></div>
Here's a useful link : https://css-tricks.com/examples/ShapesOfCSS/
SVg path and pattern
You can create your shape with a single path. I used a quadratic Bezier curve.
Path MDN
I added an image to the svg using a image tag and pattern tag.
This is then using inside the path with this fill="url(#img1)".
The defs tag is used to hide elements we are not using directly.
<svg viewBox="0 0 100 100" width="400px" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="img1" patternUnits="userSpaceOnUse" width="400" height="400">
<image xlink:href="http://lorempixel.com/400/400/" x="0" y="0" width="100px" height="100px" />
</pattern>
</defs>
<path d="M15,15 Q 50,0 85,18 100,50 85,85 50,100 18,85 0,50 15,15Z" fill="url(#img1)" />
</svg>

Box with inside curve

I've been trying to create a an 'inside curved box' with no success, I don't seem to find any example online. Can anyone help me to replicate that using just CSS or maybe SVG?
Given that the shape background is a solid color and the page background is not, you can create the shape using a pseudo-element and a box-shadow with high spread radius. Its a hackish solution but would work on most browsers as box shadow has good support.
div{
position: relative;
height: 300px;
width: 150px;
border-radius: 12px;
overflow: hidden;
}
div:after{
position: absolute;
content: '';
height: 30px;
bottom: -15px;
width: 100%;
left: 0px;
box-shadow: 0px 0px 0px 500px blue;
border-radius: 12px;
}
body{
background: linear-gradient(chocolate, brown);
height: 100vh;
}
<div class='shape'></div>
You can also achieve the same effect using SVG path elements like in the below snippet.
div {
height: 300px;
width: 150px;
}
svg path {
fill: blue;
}
body {
background: linear-gradient(chocolate, brown);
height: 100vh;
}
<svg viewBox='0 0 150 300' height='0' width='0'>
<defs>
<g id='shape'>
<path d='M0,12 A12,12 0 0,1 12,0 L138,0 A12,12 0 0,1 150,12 L150,300 A12,12 0 0,0 138,288 L12,288 A12,12 0 0,0 0,300z' id='fill' />
</g>
</defs>
</svg>
<div class='shape'>
<svg viewBox='0 0 150 300' preserveAspectRatio='none' vector-effect='non-scaling-stroke'>
<use xlink:href='#shape' />
</svg>
</div>

Internet Explorer and clip-path

As far as I'm aware clip-path should work in IE, as demonstrated in many articles and this tutorial CSS Masking
However I can't get the below to run properly on IE, but it works fine on Chrome.
.container {
position: relative;
width: 240px;
height: 500px;
left: 50%;
top: 50%;
}
.pentagon {
-webkit-clip-path: polygon(0px 0px, 100px 0px, 112px 13px, 240px 13px, 240px 250px, -250px 250px);
-o-clip-path: polygon(0px 0px, 100px 0px, 112px 13px, 240px 13px, 240px 250px, -250px 250px);
-ms-clip-path: polygon(0px 0px, 100px 0px, 112px 13px, 240px 13px, 240px 250px, -250px 250px);
float: left;
}
.avatar {
margin-top: 50px;
}
html {
text-align: center;
min-height: 100%;
background: linear-gradient(white, #ddd);
}
h1,
p {
color: rgba(0, 0, 0, .3);
}
<div class="container">
<div class="avatar">
<img class="pentagon" src="http://25.media.tumblr.com/tumblr_m5nre6cxkQ1qbs7p5o1_r1_500.jpg" alt="" />
</div>
</div>
<svg>
<defs>
<clipPath id="pentagon" clipPathUnits="objectBoundingBox">
<polygon points=".5,0 1,.30 .2,1 .2,1 0,.30" />
</clipPath>
</defs>
</svg>
After more in depth research, when working with the image directly, IE supports clip as in rectangular shapes only but not clipPath complicated shapes.
My solution was to add the image to an SVG as below, and this time it works in both Chrome and IE9+.
Demo JsFiddle
body {
background-color: #e0e0e0;
}
#image-wrapper {
position: relative;
}
.svg-background,
.svg-image {
clip-path: url(#clip-triangle);
}
.svg-image {
-webkit-transition: all 0.5s ease 0.2s;
-moz-transition: all 0.5s ease 0.2s;
opacity: 1;
transition: all 0.5s ease 0.2s;
}
svg.clip-svg {
height: 250px;
position: absolute;
width: 250px;
}
#svg-1 {
left: 0px;
top: 0px;
}
<div id="image-wrapper">
<svg id="svg-1" class="clip-svg">
<rect class='svg-background' width="300" height="300" fill="#ffffff" />
<image id="img-1" class='svg-image' width="300" height="300" xlink:href="http://25.media.tumblr.com/tumblr_m5nre6cxkQ1qbs7p5o1_r1_500.jpg" />
</svg>
</div>
<svg id="svg-defs">
<defs>
<clipPath id="clip-triangle">
<polygon points="0 0, 100 0, 112 13, 240 13, 240 250, -250 250"/>
</clipPath>
</defs>
</svg>
Look at this Demo JsFiddle it supports responsive image and well documented
.member-picture {
width: 200px; /*Final image width*/
}
.member-picture image{
width:100%; /*for responsive image behaviour*/
clip-path: url('#small-clip');
}
<svg class="member-picture">
<image xlink:href="https://via.placeholder.com/350x200"></image>
</svg>
<svg viewBox="0 0 250.35696 212.65134"> <!--viewBox = "X1 Y1 X2 Y2"-->
<defs>
<clipPath id="small-clip" clipPathUnits="objectBoundingBox"
transform="scale(.0039 .0047)">
<!--Use clipPathUnits="objectBoundingBox" and transform="scale(1/(viewBox.X2-viewBox.X1) 1/(viewBox.Y2-viewBox.Y1)" -->
<path d="M231.76,2.10959c5.989,1.0033,11.34394,3.5405,14.95847,9.74636,5.229,8.97779,3.54658,20.83845,2.65967,30.67514-4.2102,46.31217-8.047,92.66163-12.03267,138.993A28.82369,28.82369,0,0,1,235.49314,189.8c-2.913,7.28451-8.96608,11.54254-17.95131,14.28814-10.36022,3.16575-21.42435,3.0895-32.14721,3.458L40.64126,212.52043c-7.4331.25543-15.17585,0.4528-21.94517-2.62817C9.79852,205.84265,4.11114,196.65751,1.7732,187.16541S-0.05058,167.74594.329,157.97752c1.53266-39.43778.62959-78.92331,0.4924-118.39062C0.7836,28.70009,1.2929,16.57391,9.01875,8.9034,20.99475-2.98675,42.47458.45166,57.6212,0.4913q29.26963,0.07661,58.5389.24813,48.42851,0.2838,96.855.82742C219.161,1.63584,225.777,1.1073,231.76,2.10959Z"
fill="#4d4d4d">
</path>
</clipPath>
</defs>
</svg>