I want the above result, cant use the image because the height of the div is not fixed.
Any help will be appriciated.
You can use pseudo classes & gredient background to creating this. check updated snippet below ...
.msgBox {
padding: 3px;
background: #f9db31;
background: -webkit-linear-gradient(#f9db31 0%, #ff0000 100%);
background: -moz-linear-gradient(#f9db31 0%, #ff0000 100%);
background: -o-linear-gradient(#f9db31 0%, #ff0000 100%);
background: linear-gradient(#f9db31 0%, #ff0000 100%);
float: left;
margin: 50px;
position: relative;
border-radius: 5px;
}
.msgBox::before {
border-bottom: 30px solid transparent;
border-right: 30px solid #f9db31;
border-top: 0 solid transparent;
content: "";
height: 0;
left: -27px;
position: absolute;
top: 25px;
width: 0;
z-index: 999;
}
.msgBox::after {
border-bottom: 28px solid transparent;
border-right: 28px solid #fff;
border-top: 0 solid transparent;
content: "";
height: 0;
left: -21px;
position: absolute;
top: 27px;
width: 0;
z-index: 999;
}
.innerBox {
width: 400px;
min-height: 200px;
background: #fff;
border-radius: 5px;
}
<div class="msgBox">
<div class="innerBox">
</div>
</div>
SVG can be used to create such shapes. It offers simplicity and scale-ability.
However in case your case as you need flexible height element, may
be it doesn't fit your needs. I'm leaving my answer here for a possible alternate for some similar situations where it might be handy.
We can use SVG's path element to create a shape like above and stroke / fill it with some solid color, gradient or a pattern.
Only one attribute d is used to define shapes in path element. This attribute itself contains a number of short commands and few parameters that are necessary for those commands to work.
Following code will create the above shape:
<path d="M0,25 L25,30 V20
Q25,5 40,5 L460,5
Q475,5 475,20 L475,170
Q475,185 460,185 L40,185
Q25,185 25,170 L25,50 Z" />
Below is a brief description of path commands used in above code:
M command is used to define the starting point. It appears at the beginning and specify the point from where drawing should start.
L and V commands are used to draw straight lines.
Q command is used to draw curves.
Z command is used to close current path. It draws a straight line from current point to the starting point to close the shape.
Output Image:
Working Example:
body {
padding: 10px;
}
<svg width="500" height="200" viewBox="0 0 500 200">
<defs>
<linearGradient id="grad" x2="0" y2="1">
<stop offset="0" stop-color="yellow" />
<stop offset="0.5" stop-color="orange" />
<stop offset="1" stop-color="red" />
</linearGradient>
</defs>
<path d="M0,25 L25,30 V20
Q25,5 40,5 L460,5
Q475,5 475,20 L475,170
Q475,185 460,185 L40,185
Q25,185 25,170 L25,50 Z" stroke="url(#grad)" stroke-width="2" fill="none" />
</svg>
Useful Resources:
Below are some useful links for SVG:
Specification
MDN
Related
I am thinking how to style a squizzed box like this:
I found that I can achieve a similar result with pseudo elements and border-radius as percentage.
Here is the CodePen: https://codepen.io/micu22/pen/eYzpmqR
And here is the code:
div {
background: lightblue;
padding: 10px 20px;
border-radius: 8px;
position: relative;
}
div::after,
div::before {
content: "";
position: absolute;
background: white;
width: 100%;
height: 20px;
left: 0;
}
div::before {
top: -17px;
border-radius: 50%;
}
div::after {
bottom: -17px;
border-radius: 50%;
}
But maybe there is an easier or just more elegant solution?
I would do it like below, using gradient coloration and an SVG filter:
.box {
width:200px;
height:250px;
background:
/* v-- adjust the 15% here */
radial-gradient(50% 15% at top, transparent 98.5%,lightblue) top,
radial-gradient(50% 15% at bottom,transparent 98.5%,lightblue) bottom;
background-size:100% 51%;
background-repeat:no-repeat;
filter: url('#goo');
}
<div class="box"></div>
<svg style="visibility: hidden; position: absolute;" width="0" height="0" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs> <!-- adjust the the 13 here --v -->
<filter id="goo"><feGaussianBlur in="SourceGraphic" stdDeviation="13" result="blur" />
<feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -9" result="goo" />
<feComposite in="SourceGraphic" in2="goo" operator="atop"/>
</filter>
</defs>
</svg>
It depends on how the content is going to exist. If this is a fixed height container, I'd probably opt for a solution using an SVG background.
I think the most elegant (or at least intrinsic) solution would involve using clipping paths. This would allow you to create an SVG of the exact shape you want and clip the container or background image for the container so that you aren't disguising a still technically visible part of the element.
Clippy is a great tool if you've never worked with clipping masks before.
I'm trying to create a spinner where two dots intersect and the foremost one should clip the other letting the background be visible on few pixels of intersection.
It would be okay to use SVG if CSS isn't capable of this, but at the moment I can't find a way to achieve the effect in neither of the technologies.
I tried with clip-path but it doesn't seem to do what am I trying to do.
Ideas?
body {
background-image: linear-gradient(to right, yellow 0%, purple 100%);
}
.a, .b {
width: 50px;
height: 50px;
border-radius: 100%;
position: absolute;
top: 5em;
left: 50vw;
border: 4px solid white;
}
.a {
background: red;
}
.b {
background-color: blue;
margin-left: 30px;
}
<div class="a"></div>
<div class="b"></div>
It's easy to do in SVG. However you'll want to use a <mask> rather than a <clipPath>.
body {
background-image: linear-gradient(to right, yellow 0%, purple 100%);
}
svg {
margin: 5em 0 0 50vw;
}
<svg width="80" height="50">
<defs>
<mask id="clipred">
<rect width="100%" height="100%" fill="white"/>
<circle cx="55" cy="25" r="29" fill="black"/>
</mask>
</defs>
<circle cx="25" cy="25" r="25" fill="red" mask="url(#clipred)"/>
<circle cx="55" cy="25" r="25" fill="blue"/>
</svg>
I've read this great question already Transparent hollow or cut out circle
but I want to draw more circles (let's say three).
So I tried using an extra element for the circle instead of a pseudo-element (so I can add more) and it works for one circle but not for more. The problem is that they are not transparent since the last one covers everything. Here is my attempt:
body{
background-color:violet;
}
.shape{
height: 150px;
width: 150px;
position:relative;
overflow:hidden;
}
.hole{
position:absolute;
border-radius:100%;
width:30px; height:30px;
color:red;
box-shadow: 0px 0px 0px 2000px black;
}
.hole:nth-child(1) {
left:25px; top:25px;
}
.hole:nth-child(2) {
left:65px; top:25px;
}
.hole:nth-child(3) {
left:55px; top:65px;
}
<div class="shape">
<div class="hole">1</div>
<div class="hole">2</div>
<div class="hole">3</div>
</div>
Just use an svg. Black part of mask is removed from the element it is applied to and white is kept:
html, body {
height: 100%;
margin: 0;
background: linear-gradient(to top, red, blue);
}
svg {
display: block;
width: 150px;
}
<svg viewBox="0 0 150 150">
<mask id="circles" maskUnits="objectBoundingBox">
<rect x="0" y="0" width="100%" height="100%" fill="white" />
<circle cx="40" cy="40" r="15" fill="black" />
<circle cx="80" cy="40" r="15" fill="black" />
<circle cx="70" cy="80" r="15" fill="black" />
</mask>
<rect x="0" y="0" width="100%" height="100%" fill="green" style="mask: url(#circles)" />
</svg>
If you really want to make this with CSS and if you aren't afraid of multiple box-shadows, you could do this BUT you must be aware that this is hard coded and the values for box-shadow must be updated when the cirlces change position, size or number.
Here is an example of the approach you can use, the values for box shadow should be "optimized" :
body {
background: url('https://farm9.staticflickr.com/8760/17195790401_ceeeafcddb_o.jpg');background-size:cover;
}
.shape {
height: 150px;
width: 150px;
position: relative;
overflow: hidden;
}
.hole {
position: absolute;
border-radius: 100%;
width: 30px;
height: 30px;
color: red;
}
.hole:nth-child(1) {
left: 25px;
top: 25px;
box-shadow: -38px -33px 0px 55px black, 9px 14px 0px 0px black;
}
.hole:nth-child(2) {
left: 65px;
top: 25px;
box-shadow: 76px -63px 0px 100px black, -7px 6px 0px 0px black;
}
.hole:nth-child(3) {
left: 55px;
top: 65px;
box-shadow: -3px 91px 0px 100px black;
}
<div class="shape">
<div class="hole">1</div>
<div class="hole">2</div>
<div class="hole">3</div>
</div>
Other than that, I would clearly recomend using SVG either with masking/clipping or with a path as shown in the answer you linked to. Here is an example with several cut out transparent circles using the path element with the arc command :
body{background: url('https://farm9.staticflickr.com/8760/17195790401_ceeeafcddb_o.jpg');background-size:cover;}
svg{
display:block;
width:70%;
height:auto;
margin:0 auto;
}
path{
transition:fill .5s;
fill:#E3DFD2;
}
<svg viewbox="-10 -1 30 15">
<path d="M-10 -1 H30 V15 H-10z
M 5 5 m -5, 0
a 5,5 0 1,0 10,0
a 5,5 0 1,0 -10,0
M-3 10 m -2, 0
a 2,2 0 1 ,0 4,0
a 2,2 0 1 ,0 -4,0
M15 8 m -2, 0
a 2,2 0 1 ,0 4,0
a 2,2 0 1 ,0 -4,0
M-5 5 m -2, 0
a 2,2 0 1 ,0 4,0
a 2,2 0 1 ,0 -4,0"/>
</svg>
The above code is fomarted so each circle in the path element is "drawn" with :
M cx cy m -r, 0
a r,r 0 1,0 (r * 2),0
a r,r 0 1,0 -(r * 2),0
The center of the circle is cx, cy and r is its radius. See this answer for an explanation.
The first line (M-10 -1 H30 V15 H-10z) is made to make the surounding rectangle and each cirlce "cuts it out".
The advantage of this approach is that it works for all browsers that support inline svg. Even those who don't support masking or clipping.
To understand how this works, you should take a look at :
SVG in HTML (inline)
the path command
and specificaly the arc command
You can use the rgba color values specifying opacity instead of using a single color for your box-shadow to have the desired effect.
Try box-shadow: 0px 0px 0px 2000px rgba(0, 0, 0 , 0.1);
<!DOCTYPE html>
<html>
<head>
<style>
.shape{
height: 150px;
width: 150px;
position:relative;
overflow:hidden;
background-color:#333333;
}
.hole{
position:absolute;
border-radius:20px;
width:20px;
height:20px;
color:red;
background-color:white;
opacity:0.6; /* for transparency levels change between 0=invisible and 1=opaque */
text-align:center;
}
.hole:nth-child(1) {
left:25px; top:25px;
}
.hole:nth-child(2) {
left:65px; top:25px;
}
.hole:nth-child(3) {
left:55px; top:65px;
}
</style>
</head>
<body>
<div class="shape">
<div class="hole">1</div>
<div class="hole">2</div>
<div class="hole">3</div>
</div>
</body>
</html>
I am trying to develop a CSS box hover effect using HTML5 & CSS3 but I cannot get this to work. I would like to make an effect like seen below:
when the user is not hovering
when user is hovering
i.e. how can I make a blue triangle and turn it into a blue square when the user hovers over it using HTML5 and CSS3? I need this only using HTML5 & CSS3 and not using canvas.
This element work with canvas perfectly like as below
var ctx = document.getElementById("c").getContext("2d");
ctx.fillStyle = "#0000ff";
function normal() {
ctx.clearRect(0,0,256,256);
ctx.beginPath();
ctx.moveTo(256,256);
ctx.lineTo(256,0);
ctx.lineTo(0,0);
ctx.closePath();
ctx.fill(); bars()
ctx.fillStyle="#0000ff"; for (i=0;i
But I need only using HTML5 & CSS3 scripting languages
Using SVG: (the entire effect that you are looking for)
I know you've asked for HTML(5) + CSS(3) but you could also use a SVG path element to produce this effect like in the below snippet. (Note: This uses SVG animations and its browser support can be different compared to CSS animations.)
svg {
height: 150px;
width: 150px;
stroke: black;
}
#blue {
stroke: blue;
stroke-width: 10;
}
svg polygon {
fill: blue;
}
#white {
stroke: white;
stroke-width: 10;
}
#icon {
fill: transparent;
}
<svg viewBox='0 0 100 100'>
<defs>
<clipPath id='clipper' clipPathUnits='objectBoundingBox'>
<path d='M0,0 1,0 1,1 0,0z'>
<animate attributeType="XML" attributeName="d" from="M0,0 1,0 1,1 0,0z" to="M0,0 1,0 1,1 0,1z" dur="1s" begin="icon.mouseover" fill="freeze" />
<animate attributeType="XML" attributeName="d" from="M0,0 1,0 1,1 0,1z" to="M0,0 1,0 1,1 0,0z" dur="1s" begin="icon.mouseout" fill="freeze" />
</path>
</clipPath>
<g id='lines'>
<line x1='20' y1='30' x2='80' y2='30' />
<line x1='20' y1='50' x2='80' y2='50' />
<line x1='20' y1='70' x2='80' y2='70' />
</g>
</defs>
<use xlink:href='#lines' id='blue' />
<g clip-path='url(#clipper)'>
<polygon points='0,0 0,100 100,100 100,0' />
<use xlink:href='#lines' id='white' />
</g>
<g>
<polygon points='0,0 0,100 100,100 100,0' id='icon' />
</g>
</svg>
The below are answers to the question - how to turn triangle into square with animation.
Using Borders:
You could do it using border like in the below snippet. Initially only the right and top borders have the blue color but on hover we set the color to all border sides. This method is pretty simple and will work in all browsers (including IE8) but you cannot add content directly to this div (as doing so will affect the triangle shape) and so you'd have to place content on top of the shape using positioning or set the shape using a pseudo-element.
.shape{
height: 0px;
width: 0px;
border: 50px solid transparent;
border-color: blue blue transparent transparent;
transition: all 1s;
}
.shape:hover{
border-color: blue;
}
<div class='shape'></div>
Using Transforms:
You could add rotate transform on a pseudo-element, set overflow: hidden on parent to produce the triangle and then reverse/nullify the transform on hover.
.shape {
position: relative;
height: 100px;
width: 100px;
overflow: hidden;
}
.shape:after {
position: absolute;
content: '';
height: calc(100% * 1.414); /* using Pythogras theorem */
width: calc(100% * 1.414); /* using Pythogras theorem */
transform: rotate(-45deg);
transform-origin: left top;
background: blue;
transition: all 1s;
}
.shape:hover:after {
transform: rotate(0deg);
}
<div class='shape'></div>
You could also use a skewX transform instead of a rotate transform if you wish to avoid calculating the height and width like in the previous snippet.
.shape {
position: relative;
height: 100px;
width: 100px;
overflow: hidden;
}
.shape:after {
position: absolute;
content: '';
height: 100%;
width: 100%;
transform: skewX(45deg);
transform-origin: left top;
background: blue;
transition: all 1s;
}
.shape:hover:after {
transform: skewX(0deg);
}
<div class='shape'></div>
Using Gradients:
You could use linear-gradients to create a triangle and then turn it into a square on hover by doubling the background-size.
.shape{
height: 100px;
width: 100px;
background: linear-gradient(to bottom left, blue 49.5%, transparent 50.5%);
background-position: 100% 0%;
background-size: 100% 100%;
transition: all 1s;
}
.shape:hover{
background-size: 200% 200%; /* just double the background size on hover */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='shape'></div>
In spite of the complete answer from Harry, couldn't resist to post an answer with another approach, suggested by the image in the OP.
Let's use blend modes, and see what can be achieved (but with more limited support)
.test {
width: 200px;
height: 200px;
background-color: white;
display: inline-block;
background-image: linear-gradient(blue, blue), linear-gradient(blue, blue), linear-gradient(blue, blue);
background-size: 100px 30px;
background-repeaT: no-repeat;
background-position: center 30px, center center, center 140px;
border: solid 1px black;
position: relative;
overflow: hidden;
}
.test:after {
content: "";
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
background: linear-gradient(45deg, yellow 50%, transparent 50%);
mix-blend-mode: difference;
transition: all 1s;
}
.one:after {
transform-origin: bottom right;
}
.one:hover:after {
transform: rotate(-45deg);
}
.two:hover:after {
opacity: 0;
}
.three:after {
background: none;
box-shadow: -1000px 1000px 0px 1000px yellow;
transform-origin: top left;
transform: rotate3d(1,1,0,87deg);
}
.three:hover:after {
transform: rotate3d(1,1,0,0deg);
}
<div class="test one"></div>
<div class="test two"></div>
<div class="test three"></div>
the third one is a little bit tricky, and not quite perfect. But you get the idea.
I'm trying to get a heading element on my page to look like:
I saw the steps shown at CSS: :before and :after pseudo elements in practice (see heading 'Styling titles') which displays a single line before and after the heading element. I liked that idea and wanted to expand it out to display three lines as per the sample image. Unlike image I was hoping for the lines to be thinner and not take up the full height space available but that's all I could mock up with limited tools/skills.
My issue is not getting three lines, but rather aligning each of those lines to their intended place. Currently they mess up and stack in an unexpected way (at least unexpected from my understanding).
Here is a JsFiddle showing my progress so far. I've created the h1 for text and two spans either side of the text but within the h1. My reasoning for this was to remove the single line from the h1 and apply the three lines via each span utilising pseudo-elements :after and :before for two of them.
Not sure where I have gone wrong or if it is even possible. I have complete access to HTML and CSS so the structure and styles are not locked down.
Let me know if I haven't been clear.
You can do it using two spans.
.long {
position: relative;
width: 100%;
}
.long:after, .long:before {
content: '';
position: absolute;
height: 3px;
width: 30px;
background: black;
top: 50%;
left: -34px;
}
.long:before {
left: calc(100% + 4px);
}
.title {
position: relative;
font-size: 50px;
margin-left: 40px;
}
.title:after, .title:before {
content: '';
position: absolute;
height: 20%;
width: 20px;
border-top: 3px solid black;
border-bottom: 3px solid black;
top: calc(100% - 31.2%*2);
right: -24px;
}
.title:before {
right: calc(100% + 4px)
}
<span class="title"><span class="long">text</span></span>
Also, possible with svg if you want round corners.
<svg width="170" height="50" viewBox="-10 0 170 50">
<defs>
<line id="small" x1="3" y1="3" x2="20" y2="3" stroke="black" stroke-width="3" stroke-linecap="round" />
<line id="large" x1="3" y1="3" x2="30" y2="3" stroke="black" stroke-width="3" stroke-linecap="round" />
</defs>
<text x="75" y="35" text-anchor="middle" font-size="50">text</text>
<use transform="translate(5,10)" xlink:href="#small" />
<use transform="translate(-5,17)" xlink:href="#large" />
<use transform="translate(5,24)" xlink:href="#small" />
<use transform="translate(125,10)" xlink:href="#small" />
<use transform="translate(125,17)" xlink:href="#large" />
<use transform="translate(125,24)" xlink:href="#small" />
</svg>
You could use a CSS background image, or gradient to achieve the same effect.
The CSS background will be something along the lines of:
background:linear-gradient(to bottom, #fff 0%, #fff 20%, transparent 20%, transparent 40%, #fff 40%, #fff 60%, transparent 60%, transparent 80%, #fff 80%, #fff 100%);
Why not create a left and right image and display it with the :before and :after like you are but instead of setting content: add background: url('img_left.png');?
Here is a Fiddle to show what I mean.