css 3D transform elements disappear when perpendicular to viewer - html

html elements, being two dimensional,
have width & height but no thickness. not even a single pixel.
Therefore, when applying a 3D transform to an element, if its rotated perpendicularly to the viewer, it disappears.
Is there some property that can be set to remedy this situation?
It seems that the browsers should calculate elements as being 1 pixel thick if they are rotated in 3d.

I don't know if this solution applies to your case, due to the lack of details in your questions.
But, in a general way, you can do this adding a border to the element you are rotating.
There is an example: http://jsfiddle.net/4L8Ht/1/. In this case, I've added a blue border (same color of the rotated div).
HTML:
<div class="container">
<div class="rotateY r45deg"></div>
</div>
<div class="container">
<div class="rotateY r90deg"></div>
</div>
CSS:
.container {
width: 200px;
height: 200px;
margin: 50px;
border: 1px solid #ccc;
-webkit-perspective: 400;
}
.rotateY {
width: 100%;
height: 100%;
background-color: #00f;
border: 1px solid #00f;
}
.r45deg { -webkit-transform: rotateY(45deg); }
.r90deg { -webkit-transform: rotateY(90deg); }

Related

Overflow hidden does not fully hide parent div with border radius

I am getting some residual overflow from my simple layout below. Though minimal, the effect is quite obvious and happens only where I set a border radius. The expected behavior is to have the div class='inner', the white, fully cover div class='outer', the red. However there clearly seems to be residual overflows from both ends of the div.
Example:
.outer {
background-color: red;
width: 500px;
height: 50px;
position: relative;
overflow: hidden;
border-radius: 5rem;
}
.inner {
background: white;
width: 100%;
height: 100%;
position: absolute;
}
<div class="outer">
<div class="inner"></div>
</div>
I am using this as part of a loading bar effect where inner translates as part of an animation during a media play. I have read a couple other problems that involve adding properties like z-index and adding masks but does not work for me. Also read issues with webkit, but have not found anything that works in the case above.
Edit
For clearer illustration refer below:-
Overflow hidden is being used so that when inner translates, any overflow is hidden out of the parent div. I am unsure if there are any other ways I can use. Below is an example of having the x-axis translate at 10%. I am trying to achieve the overflow effect without any bleeding from the edges around where border radius is applied.
Translate starts at 0% which is the same as the example above.
This issue was also reported - Issue 491574: border-radius bleeds background-color
And similar to the question - CSS border radius background colour bleed but the use case of overflow does not apply to my case.
.outer {
background-color: red;
width: 500px;
height: 50px;
position: relative;
border-radius: 5rem;
overflow: hidden;
}
.inner {
background: white;
width: 100%;
height: 100%;
position: absolute;
transform: translateX(10%);
}
<div class="outer">
<div class="inner"></div>
</div>
The code above though not in exact flavor is embedded in an app written in ReactJS and I am facing this issue both in Chrome and Mozilla.
The answer I suggested as a duplicate mentions:
The fix would be on a case by case basis... it would be matter of rearranging the elements such that they are a top and bottom rather than a parent and child.
So here is your case fix. You have to have the background red color into a child of the container element... And the progressbar on top of it. Now that the container doesn't have any background color, nothing can bleed due to the anti-aliasing.
Additionnally, if you apply the same border-radius to the "background" div... And a 1px white border... The magic is made.
Below, I animated the width of the .progress-bar on an interval to simulate you react state based animation.
// Simulating an animation... Just for this demo.
let outer = document.querySelector(".outer")
let progress = document.querySelector(".progress-bar")
let outerWidth = outer.getBoundingClientRect().width
let progressWidth = progress.getBoundingClientRect().width
let interval = setInterval(function(){
progressWidth = progress.getBoundingClientRect().width
progress.style.width = progressWidth + 10 + "px"
if(progressWidth > outerWidth) clearInterval(interval)
},500)
.outer {
background-color: transparent;
width: 500px;
height: 50px;
position: relative;
border-radius: 5rem;
overflow: hidden;
}
.progress-background {
background: red;
width: calc(100% - 2px); /* to compensate the white border space */
height: calc(100% - 2px); /* to compensate the white border space */
position: absolute;
border-radius: 5rem; /* Same radius than the container */
border: 1px solid white; /* white border */
}
.progress-bar {
background: white;
width: 0;
height: 100%;
position: absolute;
transition: width 1s; /* Just to have the animation a bit smooter */
}
<div class="outer">
<div class="progress-background"></div>
<div class="progress-bar"></div>
</div>

CSS, height makes the border color change

Sometimes CSS acts weird in chrome, the difference between the two divs are only the height parameter, but as a result: the border color is different.
body {
background: black;
}
#div1 {
border: 1px solid white;
height: 41px;
width: 100px;
transform: rotateZ(270deg);
transform-origin: right;
}
#div2 {
border: 1px solid white;
height: 40px;
width: 100px;
transform: rotateZ(270deg);
transform-origin: right;
}
<div id="div1">
</div>
<br><br><br><br><br><br>
<div id="div2">
</div>
PS : I am working under chrome with 100% zoom
result :
This is in fact an anti aliasing issue.
The 1px border is in between two pixels, resulting in this grey looking color.
To visualize this I have taken a screenshot for you, zoomed in and put a grid over it:
Keep that in mind when transforming objects.

CSS split a square into 4 triangles

I am currently trying to make a square be 4 triangles of equal size that have hover events on them.
I am creating the triangles like this,
.right, left, .top, .bottom {
position: relative;
width: 26px;
}
.right:before{
position: absolute;
display: inline-block;
border-top: 26px solid transparent;
border-right: 26px solid #eee;
border-bottom: 26px solid transparent;
left: 26px;
top: 0px;
content: '';
}
What I am finding is that each triangle sits above one another meaning only one triangle can be hovered, here is my example,
http://codepen.io/anon/pen/qdmbKz
As you can see only the bottom triangle (hover at the bottom of the square) is hoverable. What am I doing wrong? Is there a better way of doing this?
As you have already indicated in your question, the reason why the hover works only on the bottom triangle and not the others is because the container of the bottom triangle is placed on top of the container of the other three triangles.
While using the border trick to produce triangles, the actual shape is still a square. It gets the triangle appearance only because the other three borders are transparent. Now when you hover on the shape you are actually hovering the transparent areas of the bottom triangle and not the containers of the other triangles which is why their respective hover events don't get triggered.
I would personally recommend using SVG for these type of things but the shape is not all that complex to achieve with CSS either.
SVG:
In SVG, you could make use of the polygon elements to create four triangles within the square and each polygon is hover-able separately. If they should have their own target links, you can also enclose the polygons within an a (anchor) tag.
In the snippet, I have implemented the anchor only for one triangle
.square {
height: 400px;
width: 400px;
overflow: hidden;
}
svg {
height: 100%;
width: 100%;
}
polygon {
fill: aliceblue;
stroke: crimson;
stroke-linejoin: round;
}
polygon:hover {
fill: cornflowerblue;
}
<div class='square'>
<svg viewBox='0 0 100 100'>
<a xlink:href='http://google.com'>
<polygon points='5,5 50,50 95,5' />
</a>
<polygon points='5,5 50,50 5,95' />
<polygon points='5,95 50,50 95,95' />
<polygon points='95,5 50,50 95,95' />
</svg>
</div>
CSS:
This is an adaptation of the answer posted by here by web-tiki. I am posting a separate answer because the shape in this question is much simpler and doesn't require as much work as the other one.
The square is split into four equal sized hover-able triangles using the following method:
The container is a square and has borders on all its sides. The borders are required on the parent because diagonal lines on the triangle are much much more difficult to achieve with CSS.
Four child elements are added to the container whose height and width are calculated using Pythagoras theorem. They are then positioned such that their top left corner is on the center point of the square (to help with the rotation).
All the child elements are rotated by the appropriate angles to form the triangles. The transform-origin is set as top left to have the rotation done with the parent square's center point as the axis.
The parent has overflow: hidden to prevent the other half of each square from being visible.
Note that adding text into the 4 triangles will not be straight-forward because they would also be rotated. The text would have to be put inside a child element which must either be counter rotated.
Note: The script included in the demo is the prefix free library which is used to avoid browser prefixes.
.square {
position: relative;
height: 200px;
width: 200px;
border: 2px solid crimson;
overflow: hidden;
transition: all 1s;
}
.top,
.left,
.right,
.bottom {
position: absolute;
height: calc(100% / 1.414);
width: calc(100% / 1.414);
top: 50%;
left: 50%;
border: 1px solid crimson;
transform-origin: 0% 0%;
}
.right {
transform: rotate(-45deg);
}
.bottom {
transform: rotate(45deg);
}
.top {
transform: rotate(-135deg);
}
.left {
transform: rotate(135deg);
}
.square > div:hover {
background: tomato;
}
/*Just for demo*/
.square:hover{
height: 300px;
width: 300px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='square'>
<div class="top"></div>
<div class="right"></div>
<div class="bottom"></div>
<div class="left"></div>
</div>

How to apply an opacity without affecting a child element with html/css?

I want to achieve this using html and css:
I have tried to set the opacity of the container to 0.3 and the box to 1, but it doesn't work: both divs have 0.3 opacity.
jsFiddle of my try here
The effect I am trying to achive is a popup box that comes on top of the page. It is highlighted by fading the content below (by lowering the opacity).
You can use opacity in combination with background color, like this:
#container {
border: solid gold 1px;
width: 400px;
height: 200px;
background:rgba(56,255,255,0.1);
}
#box {
border: solid silver 1px;
margin: 10px;
width: 300px;
height: 100px;
background:rgba(205,206,255,0.1);
}
<div id="container">
containter text
<div id="box">
box text
</div>
</div>
​Live demo
As far as I know you can't do it in a simple way. There a couple of options here:
Use absolute positioning to position box "inside" the container.
#container {
opacity: 0.3;
background-color: #777788;
position: absolute;
top: 100px;
left: 100px;
height: 150px;
width: 300px;
}
#box {
opacity: 1;
background-color: #ffffff;
position: absolute;
top: 110px;
left: 110px;
height: 130px;
width: 270px;
}
<div id="container"></div>
<div id="box">
<p>Something in here</p>
</div>
Use Javascript - almost the same as above, but position and size don't have to be hardcoded.
You can't apply an opacity property without affecting a child element!
"Opacity applies to the element as a whole, including its contents, even though the value is not inherited by child elements. Thus, the element and its children all have the same opacity relative to the element's background, even if they have different opacities relative to one another... If you do not want to apply opacity to child elements, use the background property instead." https://developer.mozilla.org/en-US/docs/Web/CSS/opacity
If you want the opacity to be applied only to the background, without affecting the child elements, use:
background-color: rgba(255, 255, 255, .3)
However, you can achieve the desired effect if you place them inside a div parent element and use CSS position property:
.parent {
border: solid green 3px;
position: relative;
width: 400px;
height: 200px;
}
.sibling-one {
border: solid red 3px;
position: absolute;
box-sizing: border-box;
width: 400px;
height: 200px;
opacity: .3;
}
.sibling-two {
border: solid blue 1px;
margin: 10px;
width: 200px;
height: 100px;
position: absolute;
transform: translateY(50%);
}
<div class="parent">
<div class="sibling-one">
<p>A sibling's one element</p>
</div>
<div class="sibling-two">
<p>A sibling's two element</p>
</div>
</div>
Try using rgba as a 'pre content' overlay to your image, its a good way to keep things responsive and for none of the other elements to be effected.
header #inner_header_post_thumb {
background-position: center;
background-size: cover;
position: relative;
background-image: url(https://images.pexels.com/photos/730480/pexels-photo-730480.jpeg?w=1260&h=750&auto=compress&cs=tinysrgb);
border-bottom: 4px solid #222;
}
header #inner_header_post_thumb .dark_overlay {
position: relative;
left: 0;
top: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.75);
}
header #inner_header_post_thumb .dark_overlay .container .header-txt {
padding-top: 220px;
padding-bottom: 220px;
color: #ffffff;
text-align:center;
}
header #inner_header_post_thumb .dark_overlay .container .header-txt h1 {
font-size: 40px;
color: #ffffff;
}
header #inner_header_post_thumb .dark_overlay .container .header-txt h3 {
font-size: 24px;
color: #ffffff;
font-weight: 300;
}
header #inner_header_post_thumb .dark_overlay .container .header-txt p {
font-size: 18px;
font-weight: 300;
}
header #inner_header_post_thumb .dark_overlay .container .header-txt p strong {
font-weight: 700;
}
<header>
<div id="inner_header_post_thumb">
<div class="dark_overlay">
<div class="container">
<div class="row header-txt">
<div class="col-xs-12 col-sm-12">
<h1>Title On Dark A Underlay</h1>
<h3>Have a dark background image overlay without affecting other elements</h3>
<p>No longer any need to re-save backgrounds as .png ... <strong>Awesome</strong></p>
</div>
</div>
</div>
</div>
</div>
</header>
See a working codepen here
Using background-color: rgba(#777788, 0.3); instead of opacity could maybe fix the problem.
Apply this css rule
.alpha60 {
/* Fallback for web browsers that doesn't support RGBa */
background: rgb(0, 0, 0);
/* RGBa with 0.6 opacity */
background: rgba(0, 0, 0, 0.6);
/* For IE 5.5 - 7*/
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000);
/* For IE 8*/
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000)";
}
In addition to this, you have to declare background: transparent for IE web browsers.
For more details visit the following link:
http://robertnyman.com/2010/01/11/css-background-transparency-without-affecting-child-elements-through-rgba-and-filters/
Any child of an element with opacity set will take on that opacity.
To achieve this style you could use rgba colours and filters for IE for the background, and opacity on the textual elements. So long as the second box isn't a child of one of the text elements, then it won't inherit the opacity.
Another workaround is to simply use an overlay background to create a similar effect.
I personally like a black overlay with about a 65% opacity, but for what you are trying to do you may want to use a white overlay at round 70%.
Create a small (100 x 100 or less) PNG in Photoshop or GIMP that has the color and opacity you want. Then just set that as the background of your light box.
If you create multiple PNGs at different opacities you can easily switch between them with JS or dynamically at load via backend scripting.
It's not technically what you are trying to do, but aesthetically it can give a very similar effect and UX wise accomplishes the same thing. It is also very easy to do, and widely supported across pretty much everything.
Opacity will always inherits by the child element regardless whatever the element in there, there is no workaround up to today have suggested, when the moving of the child element outside the transparency background is not an option like in a popup menu/dialog box creation, use of background with the rgba is the solution.
Here is a input box that i created that i can turn on or off with the class property invisible by javascript
<div id="blackout" class="invisible">
<div id="middlebox">
<p>Enter the field name: </p>
<input type="text" id="fieldvalue" />
<input type="button" value="OK" id="addfname" />
</div>
</div>
CSS
#blackout {
z-index: 9999;
background: rgba(200, 200, 200, 0.6);
height: 100%;
width: 100%;
display: block;
padding: 0px;
clear: both;
float: left;
position: absolute;
margin-top: -10px;
margin-right: 0px;
margin-bottom: 0px;
margin-left: -10px;
}
#blackout #middlebox {
border: thick solid #333;
margin: 0px;
height: 150px;
width: 300px;
background-color: #FFF;
top: 50%;
left: 50%;
position: absolute;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
padding: 10px 50px 0px 50px;
}
#middlebox p {
float: left;
width:100%;
clear:both;
}
#middlebox input {
clear:both;
margin-bottom:10px;
}
#middlebox input[type=text]{
width:100%;
}
#middlebox input[type=button]{
float:right;
width:30%;
}
.invisible{
visibility:hidden !important;
}
Use such elements that you can add :before or :after. My solution
<div class="container">
<div>
Inside of container element is not effected by opacity.
</div>
</div>
Css.
.container{
position: relative;
}
.container::before{
content: '';
height: 100%;
width: 100%;
position: absolute;
background-color: #000000;
opacity: .25
}
This might not be the most orthodox method but you can use a small semi-transparent background image for each div / container that repeats. It does seem that in this day and age you should be able to achieve this in pure (simple not hackish) css with no js but as the answers above show it isn't that straight forward...
Using a tiled image might seem dated but will work no worries across all browsers.
You can add a container's sibling absolutely positioned behind container, with the same size, and apply opacity to it.
And use no background on your container.
Now container's children have no opaque parent and the problem vanishes.

How do I create a circle or square with just CSS - with a hollow center?

It should just basically be an outline of the square or circle - that I can style accordingly (i.e. change the color to whatever I want, change the thickness of the border, etc.)
I would like to apply that circle or square over something else (like an image or something) and the middle part should be hollowed out, so you can see the image beneath the square or circle.
I would prefer for it to be mainly CSS + HTML.
Try This
div.circle {
-moz-border-radius: 50px/50px;
-webkit-border-radius: 50px 50px;
border-radius: 50px/50px;
border: solid 21px #f00;
width: 50px;
height: 50px;
}
div.square {
border: solid 21px #f0f;
width: 50px;
height: 50px;
}
<div class="circle">
<img/>
</div>
<hr/>
<div class="square">
<img/>
</div>
More here
You can use special characters to make lots of shapes. Examples:
http://jsfiddle.net/martlark/jWh2N/2/
<table>
<tr>
<td>hollow square</td>
<td>□</td>
</tr>
<tr>
<td>solid circle</td>
<td>•</td>
</tr>
<tr>
<td>open circle</td>
<td>๐</td>
</tr>
</table>
Many more can be found here: HTML Special Characters
i don't know of a simple css(2.1 standard)-only solution for circles, but for squares you can do easily:
.squared {
border: 2px solid black;
}
then, use the following html code:
<img src="…" alt="an image " class="squared" />
If you want your div to keep it's circular shape even if you change its width/height (using js for instance) set the radius to 50%. Example:
css:
.circle {
border-radius: 50%/50%;
width: 50px;
height: 50px;
background: black;
}
html:
<div class="circle"></div>
Circle Time! :) Easy way of making a circle with a hollow center : use border-radius, give the element a border and no background so you can see through it :
div {
display: inline-block;
margin-left: 5px;
height: 100px;
border-radius: 100%;
width:100px;
border:solid black 2px;
}
body{
background:url('http://lorempixel.com/output/people-q-c-640-480-1.jpg');
background-size:cover;
}
<div></div>
To my knowledge there is no cross-browser compatible way to make a circle with CSS & HTML only.
For the square I guess you could make a div with a border and a z-index higher than what you are putting it over. I don't understand why you would need to do this, when you could just put a border on the image or "something" itself.
If anyone else knows how to make a circle that is cross browser compatible with CSS & HTML only, I would love to hear about it!
#Caspar Kleijne border-radius does not work in IE8 or below, not sure about 9.
Shortly after finding this questions I found these examples on CSS Tricks: http://css-tricks.com/examples/ShapesOfCSS/
Copied so you don't have to click
.square {
width: 100px;
height: 100px;
background: red;
}
.circle {
width: 100px;
height: 100px;
background: red;
-moz-border-radius: 50px;
-webkit-border-radius: 50px;
border-radius: 50px;
}
/* Cleaner, but slightly less support: use "50%" as value */
<div class="square"></div>
<div class="circle"></div>
There are many other shape examples in the above link, but you will have to test for browser compatibility.
In case of circle all you need is one div, but in case of hollow square you need to have 2 divs.
The divs are having a display of inline-block which you can change accordingly. Live Codepen link: Click Me
In case of circle all you need to change is the border properties and the dimensions(width and height) of circle. If you want to change color just change the border color of hollow-circle.
In case of the square background-color property needs to be changed depending upon the background of page or the element upon which you want to place the hollow-square. Always keep the inner-circle dimension small as compared to the hollow-square. If you want to change color just change the background-color of hollow-square. The inner-circle is centered upon the hollow-square using the position, top, left, transform properties just don't mess with them.
Code is as follows:
/* CSS Code */
.hollow-circle {
width: 4rem;
height: 4rem;
background-color: transparent;
border-radius: 50%;
display: inline-block;
/* Use this */
border-color: black;
border-width: 5px;
border-style: solid;
/* or */
/* Shorthand Property */
/* border: 5px solid #000; */
}
.hollow-square {
position: relative;
width: 4rem;
height: 4rem;
display: inline-block;
background-color: black;
}
.inner-circle {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 3rem;
height: 3rem;
border-radius: 50%;
background-color: white;
}
<!-- HTML Code -->
<div class="hollow-circle">
</div>
<br/><br/><br/>
<div class="hollow-square">
<div class="inner-circle"></div>
</div>