How to do this box copy overlay effect in CSS? - css

I want to create this dialog window in CSS:
The only way I managed to come close to this was to copy the dialog window several times, tilt it with transform: rotate(..) and play a bit with z-indexes.
Could this be achieved with borders or box shadows without having to copy the original dialog window? It doesn't have to literally be there three times, of course. It can just be an illusion.

I don't think you'd be able to do it with just borders, though you could use pseudo-elements to avoid actually having to copy the element and some Z transforms to achieve this:
#modal, #modal:before, #modal:after{
width: 500px;
height: 300px;
background: whitesmoke;
border-radius: 10px;
box-shadow: 0 0 5px 5px #eee;
content: " ";
position: absolute;
}
#modal:before{
transform: rotate(-3deg) translateZ(-1px);
}
#modal:after{
transform: rotate(-6deg) translateZ(-2px);
}
#modal{
transform-style: preserve-3d;
position: relative;
margin: 50px auto;
}
<div id='modal'></div>
This basically creates two pseudo-copies of your modal and pushes them behind the original with slightly different rotation.

Related

Scooped Corners with border but only on one side

So I am trying to create scooped corner (on bottom-right only) with border around the complete structure. Please refer image below.
Check image here
I have seen many examples on how to create scooped corners on all the 4 sides and creating scooped corner on one side only. But not able to find anything this specific use case.
I am a beginner in CSS. So my question could be pretty noob also.
Thanks in advance.
As this scoop is just for visual effect rather than having any semantics attached, one way of doing this using simple CSS is to use a pseudo element to create it, have that sitting over the actual element and with a background color so it overwrites the borders at the bottom.
To make this general you can introduce CSS variables to set size and positioning in proportion but just to get you started here is an example using vmin as the unit of size:
body {
background-color: black;
}
div {
width: 90vmin;
height: 90vmin;
position: relative;
border: solid 3px lime;
border-radius: 10vmin;
background-color: gray;
}
div::after {
content: '';
position: absolute;
width: 40%;
height: 40%;
border-color: transparent transparent transparent lime;
border-width: 3px;
border-style: solid;
top: 80%;
left: 80%;
border-radius: 50%;
transform: rotate(45deg);
background-color: black;
}
<div></div>

creating separate rules for horizontal and vertical alignment in css

The plunkr link is https://plnkr.co/edit/mv3lL1vwu2LxoeFZw0TX
I want to position a div at the center of a page (vertically and horizontally). The div has a button which should be at the center of the div. I found a solution in Vertically center in viewport using CSS but it doesn't work for me. Also, I want to create two separate rules, one for vertical alignment and one for horizontal alignment and use them together (or separately) so that I can pick which element should be aligned in which way.
I do not want to use Flex, Bootstrap etc. as I am trying to understand CSS concepts.
the horizontal alignment rule is straightforward.
.center-horizontally-common-styles {
display: block;
margin: auto auto;
}
The vertical alignment rule is (modified from the SO link)
.centre-vertical-common-styles {
position: fixed;
right: 50%;
top: 50%;
transform: translateY(-50%);
transform: translateX(50%);
}
.debug-border-common-styles {
border: 3px solid black;
height:40px;
width:200px;
}
HTML
<div class="debug-border-common-styles centre-vertical-common-styles center-horizontally-common-styles">
<button type="button"> Click Me! </button>
</div>
My understanding is that right: 50%; top: 50%; will use the browser's window (viewport?) as the reference and move the div's top edge and right edge to the location which is 50% mark of the browser's respective edge's location. TranslateY and TranslateX should now move the div upwards (-50%) and towards left(50%) respectively to align the button's center to the middle of the page thus centering the button. The issues I am facing are:
1) The translateY doesn't seem to work. If I change the height of the div to say 200px. the div starts growing downwards (i.e. its top edge seem to be fixed!) It doesn't happen if the width is changed to say 200px.
.debug-border-common-styles {
border: 3px solid black;
height:200px;
width:200px;
}
2) The button inside the div is not at the center of the div. I created the following css rule for the button but translateY doesn't seem to work on this one as well.
.centre-button-vertical-common-styles {
position: absolute; /*use absolute so that the origin is no the parent div*/
right: 50%;
top: 50%;
transform: translateY(-50%);
transform: translateX(50%);
}
3) Ideally, I would like to create two separate rules, say .center-vertical and .center-horizontal and combine them to use the desired effect. But If I do something like follows, it doesn't work. Is it possible to create two separate rules?
.center-horizontally-common-styles {
display: block;
margin: auto auto;
}
Not use right here because horizontal rule should place the item in middle
.centre-button-vertical-common-styles {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
Bro, you need few arrows of style. Do like this:)
.centre-vertical-common-styles {
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.debug-border-common-styles {
border: 3px solid black;
height:40px;
width:200px;
display:flex;
align-items:center;
justify-content:center;
}

What are the calculations behind the properties in a re-rotated element?

I have been playing around with an idea of a contact card type of thing. Apparently hexagons are quite a new trend, but I'd like to keep it a tad simpler, namely: rotated squares. Considering I am quite knowledgeable with HTML and CSS, it wasn't that hard to accomplish this. In a few minutes I came up with this.
HTML
<a href="#" title="Profile of Banana">
<span style="background-image: url(http://s5.favim.com/orig/52/portrait-sigma-50mm-f1.4-hsm-canon-eos-5d-mk2-face-Favim.com-473053.jpg);">
Queen Elizabeth
</span>
</a>
CSS
a {
display: inline-block;
margin: 50px;
width: 150px;
height: 150px;
transform: rotate(45deg);
position: relative;
overflow: hidden;
}
/* Pseudo element for border */
a:after {
content: "";
display: block;
width: 142px;
width: calc(100% - 8px);
height: 142px;
height: calc(100% - 8px);
border: 2px solid white;
position: relative;
z-index: 10;
top: 4px;
left: 4px;
}
/* Span for bg-image and text */
a > span {
display: block;
height: 213px;
width: 213px;
top: -31px;
left: -31px;
position: absolute;
background-size: cover;
background-position: center;
transform: rotate(-45deg);
padding: 76px 24px 0;
}
The idea is quite simple:
Make the link itself a block element, rotated it 45 degrees. Don't forget overflow: hidden
Rotate its child 45 degrees back, apply a background-image to this element (dynamically loaded in my case, therefore inline)
This works in all major browsers and degrades gracefully into a simple square in other browsers (IE8 and below; though you might need a background size polyfill). For this reason I want to keep this HTML structure.
So, what's the problem? First of all I'd like to make it applicable to different sizes where I would only need to set the width and height of the link itself (a) after which the height and width of its child are calculated automatically - in my project I can use the relatively new CSS3 calc() function, if that's of any help, along with the beauty of SASS/SCSS. In other words, I need the ratio between the width of a and its child span. As far as I can tell, it seems that the ratio is the square root of 2: 213 / 150 = 1.42. My first question is, then, why? What's the logic and/or arithmetic behind this? Why can't the span simply take up 100% width of its parent? Why need it be exactly square root 2 times more?
Additionally, I also would like to know where the top and left values come from. I haven't figured out yet which arithmetic might be the base of is. I do know that this might be dependent on the value of transform-origin, but I don't know how exactly. In other words, is it possible with a pre-defined transform-origin value to have top and left to be zero and by doing so removing the need for a per-case calculated value? If not, how can the value of these properties be calculated based on the width value of its parent, as that's the only value that should be known?
Summary, if only the width and height of a are known, how do I:
calculate the width for its child, and how can that be explained?
calculate/use the offsets (top and left) on span and how can they be explained?
I do not want to use any JS solutions for this. If something isn't clear, please post a comment so I can clarify.
UPDATED FIDDLE
First of all, as the background-image defined for span will overlap the actual a element, it needs to be bigger. As we are talking about an angle of 45 degrees, this leads to a triangular cut-off shape in which the size of the main square (i.e. the image) is the long side, and the other two equally-sized lines are of the anchor. Therefore, the size of the image (span) should be equal to sqrt(2)*100% ~= 141.42%.
The positioning of the span then. First we rotate the image back by 45 degrees. Import for this action is that the transform-origin is set to 0 0 rather than 50% 50%. By doing so, the element is rotated around a single point right in the top middle of the rhombus. After rotating it's only a matter of translate the element on the X-axis, which can also be done with CSS transforms: translateX(-50%).
No matter what value is now passed onto a's width and height, the image should always be aligned perfectly within it, with the correct dimensions.
(In the fiddle, try giving a a value of, say, 400px. It looks nice, doesn't it? You can also give nice hover effects to the image.)
a {
display: inline-block;
width: 200px;
height: 200px;
transform: rotate(45deg) translate(50%);
position: relative;
overflow: hidden;
}
a:after {
content: "";
display: block;
width: calc(100% - 8px);
height: calc(100% - 8px);
border: 2px solid white;
position: relative;
z-index: 10;
top: 4px;
left: 4px;
}
a > span {
display: block;
height: 141.42%;
width: 141.42%;
top: 0;
left: 0;
position: absolute;
background-size: cover;
background-position: center;
transform: rotate(-45deg) translateX(-50%);
transform-origin: 0 0;
}

Off by one pixel issue in IE CSS transform

I am using transform: skew to create the effect of a down arrow on my banner image using both the :before and :after tags. The result should look like the following:
However, in IE 9-11 there seems to be a rounding issue. At some heights there is one pixel from the background image that shows below the skewed blocks resulting in the following:
In my case, the banner is a percentage of the total height of the window. Here is the some sample code which should be able to reproduce the problem:
HTML
<div id="main">
<div id="banner"></div>
<section>
<h1>...</h1>
<p>...</p>
</section>
</div>
CSS
#banner {
position: relative;
background-color: green;
width: 100%;
height: 75%;
overflow: hidden;
}
#banner:before,
#banner:after {
content: '';
display: block;
position: absolute;
bottom: 0;
width: 50%;
height: 1.5em;
background-color: #FFFFF9;
transform: skew(45deg);
transform-origin: right bottom;
}
#banner:after {
right: 0;
transform: skew(-45deg);
transform-origin: left bottom;
}
body {
background-color: #333;
position: absolute;
width: 100%;
height: 100%;
}
#main {
max-width: 40em;
margin: 0 auto;
background-color: #FFFFF9;
position: relative;
height: 100%;
}
section {
padding: 0 1em 5em;
background-color: #FFFFF9;
}
And here a working example.
Yes, seems to be a rounding issue – and I don’t know of anything that one could do to fix this. It’s in the nature of percentage values that they don’t always result in full pixel values – and how rounding is done in those cases is up to the browser vendor, I’m afraid.
I can only offer you a possible workaround (resp. “cover up”) that seems to work – if the layout really is as simple as this, and the main content area has a white background, and no transparency or background-image gets involved there.
Pull the section “up” over the banner by a negative margin of -1px (eliminated top margin of h1 here as well, otherwise it adjoins with the top margin of the section – countered by a padding-top), so that its background simply covers up that little glitch:
section {
padding: 1em 1em 5em;
background-color: #FFFFF9;
position:relative;
margin-top:-1px;
}
section h1:first-child { margin-top:0; }
Well, if you look closely, that makes the corner of triangle look slightly “cut off” (by one pixel) in those situations where the rounding glitch occurs – if you can live with that (and your desired layout allows for it), then take it :-) (And maybe serve it to IE only by some means). If not – then sorry, can’t help you there.

div slanted in 2 directions

Is it possible to create the following shape as a DIV in CSS.
The browser support is not important.
You cannot skew an element like this directly, you'll need to use two elements (or generated content) and hide certain overflow to make the flat bottom edge:
http://jsfiddle.net/6DQUY/1/
#skew {
height: 240px;
overflow: hidden;
}
.skew {
background: #000;
display: inline-block;
height: 300px;
width: 500px;
margin-top: 100px;
transform: skew(-8deg, -8deg);
}
Note: I removed the cross browser definitions for better readability.
UPDATE: This would be a more fluid example which resizes in set dimensions: http://jsfiddle.net/6DQUY/3/. Note the padding-bottom on the wrapper which defines the ratio. You may have to play around with the percentage amounts.
#skew {
padding-bottom: 20%;
overflow: hidden;
position: relative;
}
.skew {
background: #000;
position: absolute;
top: 30%;
right: 8%;
left: 8%;
height: 100%;
transform: skew(-8deg, -8deg);
}
Using SVG:
Below is a sample using SVG polygon which can also be scaled easily. Text (if required) can be absolutely positioned on top of the shape.
.shape-svg {
position: relative;
height: 100px;
width: 300px;
}
svg {
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
}
polygon {
fill: black;
}
/* Just for demo*/
.shape-svg{
transition: all 1s;
}
.shape-svg:hover {
height: 200px;
width: 600px;
}
<div class="shape-svg">
<svg viewBox='0 0 100 100' preserveAspectRatio='none'>
<polygon points='5,35 100,0 95,100 0,100' />
</svg>
</div>
The shape can be created using SVG clip path also instead of polygon.
Using CSS and Single Element:
The same shape can be achieved with CSS using only one element also. The key is to set the transform-origin as the side that is required to be straight.
.shape{
height: 100px;
width: 300px;
margin-top: 50px;
background: black;
transform-origin: 0% bottom;
transform: perspective(300px) rotateY(-15deg) skewX(-10deg);
transition: all 1s;
}
.shape:hover{
width: 350px;
height: 150px;
transform: perspective(450px) rotateY(-15deg) skewX(-10deg);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="shape"></div>
The shape achieved using this method can also be scaled. However as the height of the shape increases, the right side becomes taller and pushes the top-right corner even more higher. So, either the rotation angle needs to be decreased (or) the perspective needs to be increased (shape needs to be moved farther away) for the height of the right side to remain small enough and be within the viewing area. Or else, the margin-top should be increased.
Below is an explanation on why this happens:
Consider a rectangle positioned 300px in front of the viewer's eye. It is being rotated towards to the viewer and as the rotation happens, the side which is getting closer to the user will appear taller than the other side.
We have fixed the transform origin's x coordinate as 0% and so the height of the left side of the shape would be constant and that of the right side would keep increasing based on the rotation angle.
Because the transform origin's y coordinate is bottom, the bottom side of the shape would be kept straight and any height increase on the right side of the element would be projected upwards resulting in the shape going outside of the screen.
There is no such problem if only the width increases because the rotation angle is too minimal and so the shape's right side will never get anywhere close enough to the viewer to look very tall.
The shape in question is not an exact duplicate of the one discussed here but you can get some more ideas by looking at it :)
You could look into CSS transformations (transform) I have created a JsFiddle with a quick example.
HTML
<div class="skew"></div>
CSS
/* Skew the container one way */
.skew {
background: #000;
display: inline-block;
height: 50px;
width: 500px;
margin-top: 100px;
-webkit-transform: skewY(-5deg);
-moz-transform: skewY(-5deg);
-ms-transform: skewY(-5deg);
-o-transform: skewY(-5deg);
transform: skewY(-5deg);
}
NOTE:
You may need to include other transformations to get the unbalanced look.
--EDIT--
Here is another solution but using :before and :after CSS. JsFiddle.

Resources