I want to have a(n absolutely-positioned) rectangular mask that expands on hover to reveal its (variable height) children. Right now the way that I'm achieving this is with an absolutely positioned div that changes its left, width and max-height values. However, I'd like to make it look like it's expanding from the middle instead of revealing from the top left--and all at the same time.
<div id="container">
<div id="mask">
<div id="background"></div>
</div>
</div>
#container {
width: 300px;
height: 300px;
background-color: black;
}
#mask {
width: 50px;
max-height: 50px;
position: absolute;
top: 125px;
left: 125px;
overflow: hidden;
transition: width 1s, max-height 1s, left 1s, top 1s;
}
#background {
background-image: url(https://www.pngfind.com/pngs/m/299-2991041_memes-para-stickers-png-png-download-surprised-pikachu.png);
background-size: contain;
width: 150px;
height: 125px;
}
#mask:hover {
width: 150px;
max-height: 1000px;
left: 75px;
top: 75px;
}
Here's a codepen: https://codepen.io/jraynolds/pen/OJJxpOm
#1 – Using clip-path
Compatibility: All modern browsers apart from Edge. IE10/11 and Edge provide limited support using url() only.
Example with clip-path
To crop the image, use clip-path: inset(). In this example, we have a 120 pixel box that is reduced to 0 on hover.
.reveal {
background: url(https://i.stack.imgur.com/3v1Kz.jpg) no-repeat;
background-size: 150px;
background-position: center;
height: 300px;
width: 300px;
clip-path: inset(120px 120px 120px 120px);
transition: clip-path 0.5s;
}
.reveal:hover {
clip-path: inset(0 0 0 0);
}
/*for example*/
body {
background: linear-gradient(to bottom right, black 0%, white 100%);
height: 100vh;
}
<div class="reveal"></div>
Example with url() (not working in Edge or IE)
There was an attempt!
Create an SVG like so:
<svg>
<clipPath id="square">
<rect />
</clipPath>
</svg>
and place that in the container. The div is given clip-path: url(#square) and the width, height, x and y coordinates are provided in the CSS and changed on hover.
.reveal-url {
background: url(https://www.pngfind.com/pngs/m/299-2991041_memes-para-stickers-png-png-download-surprised-pikachu.png)
no-repeat;
background-size: 150px;
background-position: center;
height: 300px;
width: 300px;
clip-path: url(#square);
position: relative;
}
svg {
width: 100%;
height: 100%;
}
.reveal-url rect {
transition: all 0.5s;
x: 120px;
y: 120px;
width: 60px;
height: 60px;
}
.reveal-url:hover rect {
width: 100%;
height: 100%;
x: 0;
y: 0;
}
/*for example*/
body {
background: linear-gradient(to bottom right, black 0%, white 100%);
height: 100vh;
}
h1 {
font-size: 30px;
color: white;
}
<h1>This only works in Chrome and Firefox.</h1>
<div class="reveal-url">
<svg>
<clipPath id="square">
<rect />
</clipPath>
</svg>
</div>
#2 – Using Box-shadow
If you are working with solid background colours, a simple method is to use inset box-shadow to mask the contents of the container and then reduce the box shadow on hover.
.reveal {
background: #000 url(https://www.pngfind.com/pngs/m/299-2991041_memes-para-stickers-png-png-download-surprised-pikachu.png) no-repeat;
background-size: 150px;
background-position: center;
height: 300px;
width: 300px;
box-shadow: inset 0 0 0 120px #000;
transition: box-shadow 1s;
}
.reveal:hover {
box-shadow: inset 0 0 0 70px #000;
}
/*for example*/
body {
background: #000;
}
<div class="reveal"></div>
This solution works, however, it uses the mask element as a child of the background element, not the other way round.
<div id="container">
<div id="background">
<div id="mask"></div>
</div>
</div>
You simply give the mask 100% border and zero dimensions and transition to zero border and 100% dimension (transparent). Mask must have elevated z-indez. Like so:
#container
{
width: 300px;
height: 300px;
background-color: black;
position: relative;
}
#mask
{
position: absolute;
left: 0;
top: 0;
z-indez: 10;
height: 0;
width: 0;
transition: 0.4s ease;
border: 150px solid black;
}
#background
{
background-image: url(https://www.pngfind.com/pngs/m/299-2991041_memes-para-stickers-png-png-download-surprised-pikachu.png);
background-size: contain;
width: 300px;
height: 300px;
display: block;
margin: 1rem auto;
}
#background:hover #mask
{
border: 0 solid black;
width: 100%;
height: 100%;
}
Here's a pen:
https://codepen.io/jaycodist/full/MWWEpMx
Related
As such: https://i.stack.imgur.com/UdHNE.png
CSS border, clip path, etc?
I've tried the following:
div#box{
width: 38px;
height: 500px;
border: 13px solid black;
border-color: transparent black transparent transparent;
border-radius: 0 100% 100% 0;
}
<div id="box"></div>
But it's not giving me the result I'm looking for (the curve is too subtle).
I've also tried using clip path but the transparent element won't "cut" into the other one obviously since it's transparent.
body {
background-color: lightblue;
}
.one {
height: 500px;
width: 38px;
background-color: white;
clip-path: ellipse(38px 50% at 0% 50%);
position: absolute;
right: 50%;
top: 0;
}
.two {
height: 500px;
width: 38px;
background-color: transparent;
clip-path: ellipse(38px 50% at 0% 50%);
position: absolute;
right: calc(50% + 13px);
top: 0;
}
<div class="one"></div>
<div class="two"></div>
Any help would be greatly appreciated.
Can you please try this and only play with second[180%] and third[-2%] value.
In here we create a required clip-path than we create another div which will create us a middle space and aplly position: absolute ,overflow:hidden to create same clip-path in red div and than we set background-color of middle div as same as screens background-color.
z-index are need to be .one > .middle > .two
clip-path: ellipse(100% 180% at -2% 50% )
body {
position: relative;
min-height: 100vh;
display: flex;
place-items: center;
background-color: bisque;
}
.one{
position: relative;
height: 500px;
width: 500px;
background-color: green;
clip-path: ellipse(100% 180% at -2% 50% ) ;
z-index: 3;
}
.middle{
position: absolute;
z-index: 2;
height: 500px;
width: 500px;
clip-path: ellipse(100% 180% at -2% 50% ) ;
left:25px;
overflow: hidden;
background-color: bisque;
}
.two{
position: relative;
z-index: 1;
right:25px;
height: 500px;
width: 500px;
background-color: red;
}
<div class="one"></div>
<div class="middle"></div>
<div class="two"></div>
I have a div with a background image, what I would like to do, is when I hover over it, the hidden part of background-image to display like in the example below:
My jsfiddle example:
div.test {
background: url(http://media2.intoday.in/indiatoday/images/Photo_gallery/emraan_012315020812.jpg);
background-size: cover;
width: 70px;
height: 70px;
background-position: center;
border-radius: 100%;
display: inline-block;
transition: all 1s;
position: absolute;
top: 100px;
}
.test:hover{
transform: scale(1.2);
}
body {
text-align: center;
}
<div class="test">
</div>
As you can see, in my example the image is just getting larger, instead I want to display another 20px of the image (without compromising border-radius).
Example with one html element:
div.test {
background: url(http://media2.intoday.in/indiatoday/images/Photo_gallery/emraan_012315020812.jpg) no-repeat 50% 50%;
background-size: 140px;
width: 70px;
height: 70px;
background-position: center;
border-radius: 100%;
display: inline-block;
transition: all 1s;
position: absolute;
top: 100px;
transform-origin: center center;
}
.test:hover{
width: 90px;
height: 90px;
margin-left: -10px;
margin-top: -10px;
}
body {
text-align: center;
}
<div class="test">
</div>
Example with clip-path and shape-inside:
div.test {
background: url(http://media2.intoday.in/indiatoday/images/Photo_gallery/emraan_012315020812.jpg) no-repeat 50% 50%;
background-size: cover;
shape-inside: circle(30% at 50% 50%);
clip-path: circle(30% at 50% 50%);
-webkit-clip-path: circle(30% at 50% 50%);
width: 70px;
height: 70px;
background-position: center;
display: inline-block;
transition: all 1s;
position: absolute;
top: 100px;
transform-origin: center center;
}
.test:hover{
shape-inside: circle(50% at 50% 50%);
clip-path: circle(50% at 50% 50%);
-webkit-clip-path: circle(50% at 50% 50%);
}
body {
text-align: center;
}
<div class="test">
</div>
you might oversize a bit the background image
(background-size:auto 90px;) and add some padding and reset position on hover (.test:hover{padding:10px; margin:-10px;})
those rules are suppose to be understood by most of actual browsers if not all.
div.test {
background: url(http://media2.intoday.in/indiatoday/images/Photo_gallery/emraan_012315020812.jpg);
background-size:auto 90px;
width: 70px;
height: 70px;
background-position: center;
border-radius: 100%;
display: inline-block;
transition: all 1s;
position: absolute;
top: 100px;
}
.test:hover{
padding:10px;
margin:-10px;;
}
body {
text-align: center;
}
<div class="test">
</div>
another possibility is to use an inset shadow
div.test {
background: url(http://media2.intoday.in/indiatoday/images/Photo_gallery/emraan_012315020812.jpg);
background-size: auto 90px;
width: 90px;
height: 90px;
/* hide buggy ff render */
background-clip: content-box;
padding: 1px;
/* end fix ff */
background-position: center;
border-radius: 100%;
display: inline-block;
transition: all 1s;
position: absolute;
top: 90px;
box-shadow: inset 0 0 0 10px white;
}
.test:hover {
box-shadow: inset 0 0 0 0px white;
}
body {
text-align: center;
}
<div class="test">
</div>
There is also : padding, box-sizing and background-clip
div.test {
background: url(http://media2.intoday.in/indiatoday/images/Photo_gallery/emraan_012315020812.jpg) ;
background-size: auto 90px;
width: 90px;
height: 90px;
padding: 10px;
background-clip:content-box;
box-sizing:border-box;
background-position: center;
border-radius: 100%;
display: inline-block;
transition: all 1s;
position: absolute;
top: 90px;
}
.test:hover {
padding:0px;
}
/* show transparency */
html {
min-height:100%;
text-align: center;
background:linear-gradient(45deg, gray, yellow,purple,lime,pink,turquoise, gray, yellow,purple,lime,pink,turquoise);
}
<div class="test"></div>
You are missing to remove border-radius property on the hover event:
div.test {
background: url(http://media2.intoday.in/indiatoday/images/Photo_gallery/emraan_012315020812.jpg);
background-size: cover;
width: 70px;
height: 70px;
background-position: center;
border-radius: 100%;
display: inline-block;
transition: all 1s;
position: absolute;
top: 100px;
}
.test:hover{
transform: scale(1.2);
border-radius: 0px;
}
body {
text-align: center;
}
<div class="test">
</div>
I want to draw 2 parallel diagonal lines on the background of my div.
Please see my table here:
body {
background-image: url("http://i.imgur.com/TnPgXl4.jpg");
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
background-repeat: no-repeat;
padding: 40px;
}
#table {
width: 800px;
height: 300px;
background-color: transparent;
border: solid 1px white;
}
<div id="table"></div>
I want to achieve something like this:
You can achieve the 2 diagonal lines with a rotated pseudo element. The 2 lines are the top and bottom borders of the absolutely positioned pseudo element:
body {
background-image: url("http://i.imgur.com/TnPgXl4.jpg");
background-size: cover;
background-repeat: no-repeat;
padding: 40px;
}
#table {
position: relative;
width: 800px; height: 300px;
background-color: transparent;
border: solid 1px white;
overflow: hidden;
}
#table:before {
content: '';
position: absolute;
right: 30%; bottom: 100%;
height: 20px; width: 100%;
border-top: 1px solid #fff;
border-bottom: 1px solid #fff;
transform-origin: 100% 100%;
transform: rotate(-70deg);
}
<div id="table"></div>
This is how this works :
the width between the 2 lines is controled by the height of the pseudo element
the thickness of the lines is controled by the border-width
the slant of the lines is controled by the rotation angle
the overflowing parts of the lines are hidden with the overflow:hidden; property on the div
Note that you need to add vendor prefixes to the transform and transform origin properties for browser support and you probably don't need the vendor prefixes on the background-size property:
canIuse for background-size
canIuse for 2D transforms
You can do this with :after and :before pseudo elemnts and trasform: rotate()
body {
background-image: url("http://www.planwallpaper.com/static/images/cool-background.jpg");
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
background-repeat: no-repeat;
padding:40px;
}
#table {
width: 70%;
height: 300px;
background-color: transparent;
border: solid 1px white;
margin: 0 auto;
position: relative;
box-sizing: border-box;
}
#table:before, #table:after {
content: "";
position: absolute;
left: 60%;
height: 102%;
border-left: 1px solid white;
transform: rotate(10deg);
transform-origin: top;
}
#table:after {
left: 65%;
}
<div id="table"></div>
An alternative to wek-tiki and Nenad Vracar's answers would be to use the skewX() CSS transform.
This solution won't require you to hide anything that overflows the edge and therefore adds a little more flexibility.
body {
background-image: url("http://i.imgur.com/TnPgXl4.jpg");
background-size: cover;
background-repeat: no-repeat;
padding: 40px;
}
#table {
position: relative;
width: 800px;
height: 300px;
background-color: transparent;
border: solid 1px white;
}
#table:before {
content: '';
position: absolute;
left: 50%;
top: 0;
height: 100%;
width: 20px;
border-right: 1px solid #fff;
border-left: 1px solid #fff;
transform-origin: 100% 100%;
transform: skewX(-20deg);
}
<div id="table"></div>
Svg
You could use an svg element and span the svg to your div.
body {
background-color: #222;
margin: 20px;
}
.container {
width: 100%;
height: 150px;
border: 2px solid white;
}
.container svg {
width: 100%;
height: 100%;
}
<div class="container">
<svg viewBox="0 0 100 100">
<line stroke="white" x1="47" x2="57" y1="100" y2="0" />
<line stroke="white" x1="57" x2="67" y1="100" y2="0" />
</svg>
</div>
This is what I'm looking for:
I have cropped an image with my html and css but have no idea how to place rectangle in it. I guess for animation I should use :hover option for my crop class in div.
My code: http://jsfiddle.net/8t2hmxmn/
I guess this will fit your needs, to adjust the height of the details element, just edit the height: value inside .details
html * {
box-sizing: border-box;
}
.crop {
background-image: url('http://cs628119.vk.me/v628119319/10059/Ag3oy3YU6wY.jpg');
width: 200px;
height: 150px;
background-position: center;
background-size: cover;
position: relative;
overflow: hidden;
}
.shape {
width: 200px;
height: 50px;
color: black;
}
.details {
position: absolute;
bottom: -100%;
left: 0;
right: 0;
height: 100%;
background: rgba(0, 0, 0, 0.5);
padding: 5px 10px;
transition: all 1s;
color: white;
}
.crop:hover > .details {
bottom: 0;
}
<div class="shape">
<div class="crop">
<div class="details">
Yes, this is cat!
</div>
</div>
</div>
The code below will create an arrow right below an <a> element:
JSFiddle
.btn {
position: relative;
display: inline-block;
width: 100px;
height: 50px;
text-align: center;
color: white;
background: gray;
line-height: 50px;
text-decoration: none;
}
.btn:after {
content: "";
position: absolute;
bottom: -10px;
left: 0;
width: 0;
height: 0;
border-width: 10px 50px 0 50px;
border-style: solid;
border-color: gray transparent transparent transparent;
}
Hello!
The problem is that we have to indicate the link width to get an arrow of a proper size because we cannot indicate the border width in pixels.
How to make a responsive triangle percent based?
You could use a skewed and rotated pseudo element to create a responsive triangle under the link :
DEMO (resize the result window to see how it reacts)
The triangle maintains it's aspect ratio with the padding-bottom property.
If you want the shape to adapt it's size according to it's content, you can remove the width on the .btn class
.btn {
position: relative;
display: inline-block;
height: 50px; width: 50%;
text-align: center;
color: white;
background: gray;
line-height: 50px;
text-decoration: none;
padding-bottom: 15%;
background-clip: content-box;
overflow: hidden;
}
.btn:after {
content: "";
position: absolute;
top:50px; left: 0;
background-color: inherit;
padding-bottom: 50%;
width: 57.7%;
z-index: -1;
transform-origin: 0 0;
transform: rotate(-30deg) skewX(30deg);
}
/** FOR THE DEMO **/
body {
background: url('http://i.imgur.com/qi5FGET.jpg');
background-size: cover;
}
Hello!
For more info on responsive triangles and how to make them, you can have a look at
Triangles with transform rotate (simple and fancy responsive triangles)
Another solution to this would be to use a CSS clip-path to clip a triangle out of a coloured block. No IE support however, but could be used for internal tools etc.
DEMO
Written with SCSS for ease.
.outer {
background: orange;
width: 25%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 1em;
p {
margin: 0;
text-align: center;
color: #fff;
}
&:after {
content: '';
position: absolute;
top: 100%;
left: 0;
right: 0;
padding-bottom: 10%;
background: orange;
-webkit-clip-path: polygon(0% 0%, 100% 0%, 50% 100%);
clip-path: polygon(0% 0%, 100% 0%, 50% 100%);
}
}
I found solution that works with any width/height. You can use two pseudo-elements with linear-gradient background, like this, (fiddle):
.btn {
position: relative;
display: inline-block;
width: 100px;
height: 50px;
text-align: center;
color: white;
background: gray;
line-height: 50px;
text-decoration: none;
}
.btn:before {
content: "";
position: absolute;
top: 100%;
right: 0;
width: 50%;
height: 10px;
background: linear-gradient(to right bottom, gray 50%, transparent 50%)
}
.btn:after {
content: "";
position: absolute;
top: 100%;
left: 0;
width: 50%;
height: 10px;
background: linear-gradient(to left bottom, gray 50%, transparent 50%)
}
A modified version of the below code can help you to achieve this
HTML
<div class="triangle-down"></div>
CSS
.triangle-down {
width: 10%;
height: 0;
padding-left:10%;
padding-top: 10%;
overflow: hidden;
}
.triangle-down:after {
content: "";
display: block;
width: 0;
height: 0;
margin-left:-500px;
margin-top:-500px;
border-left: 500px solid transparent;
border-right: 500px solid transparent;
border-top: 500px solid #4679BD;
}
For further reading on responsive triangles: CSS triangles made responsive
(archived link)
I tried the other answers and found them to be either too complex and/or unwieldy to manipulate the shape of the triangle. I decided instead to create a simple triangle shape as an svg.
The triangle height can be set to an absolute value, or as a percentage of the rectangle so it can be responsive in both directions if necessary.
html, body{
height:100%;
width:100%;
}
.outer{
width:20%;
height:25%;
background:red;
position:relative;
}
.inner{
height:100%;
width:100%;
background-color:red;
}
.triangle-down{
height:25%;
width:100%;
position:relative;
}
.triangle-down svg{
height:100%;
width:100%;
position:absolute;
top:0;
}
svg .triangle-path{
fill:red;
}
<div class="outer">
<div class="inner"></div>
<div class="triangle-down">
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" viewBox="0 0 2 1">
<g>
<path class="triangle-path" d="M0,0 l2,0 l-1,1 z" />
</g>
</svg>
</div>
Tested FF, Chrome, IE, Edge, mob Safari and mob Chrome
Another option would be to use background liner gradients, and flex positioning to make sure that the triangle always scales to its parent container. No matter how wide or narrow you make that container, the triangle always scales with it. Here is the fiddle:
https://jsfiddle.net/29k4ngzr/
<div class="triangle-wrapper-100">
<div class="triangle-left"></div>
<div class="triangle-right"></div>
</div>
.triangle-wrapper-100 {
width: 100%;
height: 100px;
display:flex;
flex-direction: column;
flex-wrap: wrap;
}
.triangle-right {
right: 0px;
background: linear-gradient(to right bottom, #6940B5 50%, transparent 50%);
width: 50%;
height: 100px;
}
.triangle-left {
left: 0px;
background: linear-gradient(to right bottom, #6940B5 50%, transparent 50%);
width: 50%;
height: 100px;
transform: scaleX(-1);
}
I took #Probocop's answer and come up with the following:
<style>
.btn {
background-color: orange;
color: white;
margin-bottom: 50px;
padding: 15px;
position: relative;
text-align: center;
text-decoration: none;
}
.btn:after {
background-color: inherit;
clip-path: url('data:image/svg+xml;utf8,%3Csvg xmlns="http://www.w3.org/2000/svg"%3E%3Cdefs%3E%3CclipPath id="p" clipPathUnits="objectBoundingBox"%3E%3Cpolygon points="0 0, 1 0, 0.5 1" /%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E#p'); /* fix for firefox (tested in version 52) */
clip-path: polygon(0% 0%, 100% 0%, 50% 100%);
content: '';
height: 50px;
left: 0;
position: absolute;
right: 0;
top: 100%;
}
</style>
Hello!
This works in Chrome and I've added a fix for Firefox. It doesn't work in Edge, however if you decrease the height of the down arrow then it doesn't look so bad.
Please note that if you are using bootstrap you will need to either change the name or override some of the styles it applies. If you decide to rename it then you also need to add the following to the .btn style:
box-sizing: content-box;