I am having trouble placing a container on top of another container that uses a clipped-path. I have tried using z-index on either of the containers but it doesn't seem to help.
If I remove the clipped-path class from the container then the block slides happily over the container. I have included a fiddle of my problem.
Here is my code:
window.onscroll = function(){
var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
var para = Math.round(scrollTop / 1.2);
document.querySelector('#block').style.transform = "translate3d(0px," + para + "px,0px)";
}
body {margin: 5px;}
#main {height:100vh;}
#below-main {height:100vh;}
#row1 {height:100vh;}
/* Paralellogram to slide underneath block
--------------------------------------------- */
#bluestripe {
height: 60vh;
width:60vw;
margin: 0 auto;
}
img {width: 100%;}
.clip-polygon {clip-path: polygon(100% 0, 100% 40%, 0 100%, 0 60%);}
/* Block to sit above parallelogram
--------------------------------------------- */
#block {
height: 50px;
width:100px;
margin: 50px auto 0 auto;
transform: translate3d(0px,0px,0px);
background-color: #999;
}
<body>
<div id="main">
<div id="block">This needs to slide on top</div>
<div id="bluestripe">
<img id="sea" src="https://images.pexels.com/photos/6644/sea-water-ocean-waves.jpg?w=940&h=650&auto=compress&cs=tinysrgb" alt="" class="clip-polygon">
</div>
<div id="row1"></div>
</div>
</body>
To affect an element's z-index, it must have position set to something other than static (the default).
In the case of your #block, it has no position set, so it is using the layer implied by the element's order in the source: it appears in your source before your clipped element, and naturally settles below it.
To position it on a higher z-index in the stack, give it a position and a z-index:
#block {
height: 50px;
width: 100px;
margin: 50px auto 0 auto;
transform: translate3d(0px,95px,0px);
background-color: #999;
position: relative; /* Allows z-index to take affect */
z-index: 2; /* Stacks it above the clipped layer, which has no position nor z-index and is at z-index 1 */
}
Related
I have a div with this css rule:
.somediv {
aspect-ratio: 1 / 3 !important;
}
I want to make the height equal not exactly (3 * width), but plus 8 pixels. For example, if my width is 10px, the height have to be like (10*3)+8 = 38 pixels. How can i do this, i know about calc() in css, but not sure it works with aspect-ratio.
If you are to set a fixed width , you may use CSS var() to set the width, then use calc() for aspect-ratio
examples
:root {
--width: 80;
}
div {
margin: 1em;
border: solid;
width: calc(var(--width) * 1px);
aspect-ratio: var(--width) / calc(var(--width) * 3 + 8);
/* demo purpose */
float: left;
}
div:before{
content:attr(style);
<div>défault</div>
<div style="--width:100"> </div>
<div style="--width:101"> </div>
<div style="--width:70"> </div>
<div style="--width:90"> </div>
If width is not, then javascriipt will be required
You can add a padding-top on the element you are styling for its size. It's counter intuitive because the size is supposedly ruled by the element width and its aspect-ratio but as you can see here in this demo, I show the computed width and height of the elements inside an ::after pseudo element through a data attribute I set via javascript with the actual offsetWidth and offsetHeight.
Given the width as 100px the height is indeed width*3 + 8px = 308px
const target = document.querySelector('div');
target.dataset['width'] = `${target.offsetWidth}px*${target.offsetHeight}px`;
.width-100{
width: 100px;
}
.ratio-1over3 {
aspect-ratio: 1 / 3;
padding-top: 8px;
}
.outline{
outline: solid red;
}
.ratio-1over3::after {
content: attr(data-width);
display: block;
}
<div class="ratio-1over3 width-100 outline">
</div>
You could use two <div>, a parent, with the dimensions and the aspect ratio, and a child with the calc():
.somediv {
width: 100%; /* or any width you want */
height: auto;
aspect-ratio: 1 / 3 !important;
}
.somediv__inner {
width: 100%;
height: calc(100% + 8px);
background: blue;
}
<div class="somediv">
<div class="somediv__inner"></div>
</div>
So I created a box with 2 div tags, namely: outer div and box div.
The total width(content block) of my outer div is 600w+50padLeft+50padRight= 700px. Meanwhile the total width of my box div (containing block) is 500w+98padL+98padR+4border = 700px.
Yet, my box is overflowing in the outer div.
Here is the image:
https://www.flickr.com/photos/183721425#N02/48599642452/in/dateposted-public/
aside,
article,
section,
header,
footer,
nav {
display: block;
}
div,
p {
margin: 0;
padding: 0;
}
html {
background: #ccc;
}
.outer {
/* TOTAL WIDTH: 700px */
width: 600px;
margin: 0 auto;
background: #9CF;
padding: 50px;
}
.box {
background: #B7D19C;
/* TOTAL WIDTH: 700px */
width: 500px;
padding: 98px;
border: 2px black solid;
}
p {
background: #FF9;
height: 100%;
/* here */
}
<div class="outer">
<div class="box">
<p>Here we'll need to calculate the width of this interior div element. This may seem simple at first, but as we begin to add box model properties, and as the overall width of the parent element and the div conflict with one another, we'll need to understand
how each of the properties combine to effect the overall width (and height) of page elements.
</p>
</div>
</div>
Use box-sizng:border-box property.
It defines how the width and height of an element are calculated, should they include padding and borders, or not. Margin is not considered. Usually the size (width or height) of the element not include border or padding
*{
box-sizing: border-box;
}
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>calculating element dimensions</title>
<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<style>
aside,
article,
section,
header,
footer,
nav {
display: block;
}
div,
p {
margin: 0;
padding: 0;
}
html {
background: #ccc;
}
.outer {
/* TOTAL WIDTH: 700px */
width: 600px;
margin: 0 auto;
background: #9CF;
padding: 50px;
}
.box {
background: #B7D19C;
/* TOTAL WIDTH: 700px */
width: 500px;
padding: 98px;
border: 2px black solid;
}
p {
background: #FF9;
height: 100%;
/* here */
}
/*add styles here*/
</style>
</head>
<body>
<div class="outer">
<div class="box">
<p>Here we'll need to calculate the width of this interior div element. This may seem simple at first, but as we begin to add box model properties, and as the overall width of the parent element and the div conflict with one another, we'll need to
understand how each of the properties combine to effect the overall width (and height) of page elements.
</p>
</div>
</div>
</body>
</html>
Problem :
Your issue is with the box model itself as by default the border and the padding are not included in the actual elements width :
.outer has a width of 600px and has a 50px of padding (total width is 600px + 50px right padding + 50px left padding = 700px) so the .box will be shifted 50px to the right.
.box has 500px for the width, 98px for the padding and a 2px border which results in a 500px + 98px right padding + 98px left padding + 2px left border + 2px right border =700px.
the widths are equal but don't forget about the 50px of padding on the .outer that results on an overflow.
Solution :
The solution is very simple, add box-sizing: border-box on the two divs (better to use it on all the elements) which includes the padding and border on the width (meaning the padding and border won't overflow the declared width).
* {
box-sizing: border-box; /** that's it ! **/
}
aside,
article,
section,
header,
footer,
nav {
display: block;
}
div,
p {
margin: 0;
padding: 0;
}
html {
background: #ccc;
}
.outer {
/* TOTAL WIDTH: 700px */
width: 600px;
margin: 0 auto;
background: #9CF;
padding: 50px;
}
.box {
background: #B7D19C;
/* TOTAL WIDTH: 700px */
width: 500px;
padding: 98px;
border: 2px black solid;
}
p {
background: #FF9;
height: 100%;
/* here */
}
<div class="outer">
<div class="box">
<p>Here we'll need to calculate the width of this interior div element. This may seem simple at first, but as we begin to add box model properties, and as the overall width of the parent element and the div conflict with one another, we'll need to understand
how each of the properties combine to effect the overall width (and height) of page elements.
</p>
</div>
</div>
I want to move a div across a screen. The div is set to width:100% initially. But when the transformation starts, the size of the div seems to have shrinked (the blue border just wraps around the text). Why it is the case?
Before
After
Here is my code example
http://codepen.io/kongakong/pen/MKzmMm
Javascript:
$(document).ready(function () {
init();
});
function init() {
$('input').on('click',
function () {
$('.answer-text-2').closest('.answer').addClass('textout');
$('.answer-hide').addClass('textin');
});
}
css
.row {
}
.hidden {
display: none;
}
.answer-text-2 {
color: red;
opacity: 1;
margin: auto;
}
.answer-text-2-new {
color: blue;
opacity: 0;
margin: 500;
}
.textout {
/* display: none; */
margin: -500;
opacity: 0;
width: '50%';
transition: all 3s ease-in-out;
}
.answer-hide {
border: 1px solid blue;
width: '100%';
}
.textin {
position: absolute;
margin: 0;
left: 0;
transform: translateX(10000px);
transition: transform 5s ease-in-out;
}
Html
<div class="contrainer">
<div>
<input type='button' value="test"></input>
</div>
<div class="row">
<div class="answer">
<span class="answer-text-2">To disappear</span>
</div>
<div class="answer-hide">To move sideway
</div>
</div>
</div>
Well... Your width of a div called answer-hide is set to auto, and it's position is set to static (as for default values). When applying transformation div's position is automatically changed to absolute (as defined in spec) and width:auto for block elements positioned absolutely is something like shrink to fit. To fix that, be sure, that your width property is properly set, because width: 100%; is not equal to width: '100%'; :)
.answer-hide {
border: 1px solid blue;
width: 100%;
}
At the beginning, you use
width: '100%';
This is not a valid value, because width expects a length, not a string. So it's ignored.
Therefore, it has the initial width: auto. For block-level, non-replaced elements in normal flow this is the width of the containing block (subtracting margins, paddings and borders).
Then, you use
position: absolute;
For absolutely positioned, non-replaced elements, when width and right are auto, and left is not, the width is given by the shrink-to-fit algorithm (also called fit-content).
That's why it shrinks.
This question already has answers here:
Setting Element Width Based on Height Via CSS
(10 answers)
Closed 3 years ago.
I saw solution for height depending on width: css height same as width. Or here: https://stackoverflow.com/a/6615994/2256981.
But my question is opposite.
My element:
<body>
<div id="square"></div>
</body>
Style for it:
body, html {
margin: 0;
height: 100%;
min-height: 300px;
position: relative;
}
div#square { /* My square. */
height: 75%; /* It's height depends on ancestor's height. */
width: 75vh; /* If supported, preliminarily sets it's width. */
position: absolute; /* Centers it. */
left: 50%; top: 50%; transform: translate(-50%, -50%);
background-color: darkorange; /* Makes it visible. */
}
Script, that keeps it square:
window.onload = window.onresize = function (event) {
var mySquare = document.getElementById("square");
mySquare.style.width = mySquare.offsetHeight + 'px';
};
Complete code here: http://jsfiddle.net/je1h/hxkgfr9g/
The question is to make the same thing in pure CSS. No scripting.
There are two techiques I am aware of to keep the aspect ratio of an element according to it's height :
When height is relative to the viewport :
You can use vh units :
div {
width: 75vh;
height: 75vh;
background:darkorange;
}
<div></div>
For a height based on the height of a parent element :
You can use a dummy image that has the aspect ratio you want. Example with a 1:1 aspect ratio you can use a 1*1 transparent .png image or as commented by #vlgalik a 1*1 base64 encoded gif :
html,body{
height:100%;
margin:0;
padding:0;
}
#wrap{
height:75%;
}
#el{
display:inline-block;
height:100%;
background:darkorange;
}
#el img{
display:block;
height:100%;
width:auto;
}
<div id="wrap">
<div id="el">
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">
</div>
</div>
Note that this last demo doesn't update on window resize. But the aspect ratio is kept on page load
UPDATE :
As reported in the comments setting display:inline-flex: on #el seems to solve the updating on window resize problem.
Edit: Missed that you wanted to set the width depending of the height, this does the opposite :(
To support all ratios you can use padding-bottom. Percentages in padding-bottom are always relative to the width of the element:
/* the wrapper has a width */
.wrapper {
position: relative;
width: 25%;
margin-bottom: 10px;
}
/* these elements set the height (using padding-bottom) */
.square {
padding-bottom: 100%;
position: relative;
}
.widescreen {
padding-bottom: 56.25%; /* 9/16 = 0.5625 */
}
/*
* This is the content.
* Needs position:absolute to not add to the width of the parent
*/
.content {
/* fill parent */
position: absolute;
top: 0; bottom: 0;
left: 0; right: 0;
/* visual */
padding: 10px;
background: orange;
color: white;
}
<div class="wrapper">
<div class="square">
<div class="content">square</div>
</div>
</div>
<div class="wrapper">
<div class="widescreen">
<div class="content">16:9 ratio</div>
</div>
</div>
The only downside is, that you need a bunch of wrapper elements.
I want 3 columns
here is the code I have
div id="boundaries">
<div id="fenceleft"><img src="<?php bloginfo('stylesheet_directory'); ?>/img/fencescew.png" alt="fencescew" width="52" height="92" /></div>
<div id="fence"></div>
<div id="fenceright"><img src="<?php bloginfo('stylesheet_directory'); ?>/img/fencescew.png" alt="fencescew" width="52" height="92" /></div>
</div>
and the CSS
#boundaries {
overflow: hidden;
position:absolute;
top:240px;
display:block;
width:100%;
max-width: 1395px;
height:92px;
z-index: 15;
}
#fenceleft {
float:left;
display: block;
width:52px;
max-width: 52px;
height:92px;
}
#fenceleft IMG {
-moz-transform: scaleX(-1); /* For Mozilla Firefox */
-o-transform: scaleX(-1); /* For Opera */
-webkit-transform: scaleX(-1); /* For Safari, Google chrome */
/* For IE */
filter: FlipH;
-ms-filter: "FlipH";
}
#fence {
float: left;
background: url(img/fence.png) repeat-x;
display: block;
height:82px;
}
#fenceright {
float:right;
display: block;
width:52px;
max-width: 52px;
height:92px;
}
Inside the boundaries div I want fence left and fence right to contain a fixed width image which they do. I want the #fence div to fill the remaining space between the two divs the right image needs to be fixed to the right hand side of the page and the left, the left hand side. the remainder I would like to have a div.
NOTE this question is common but my problem unique. the problem is that the middle or '#fence' div has no content and just a background image. with this selected code nothing displays because it has no content to fill the width.
to sum up i want [52px div fixed left] [remaining width div] [52px div fixed right]
As I understand you need something like this:
html:
<div class="leftFence"></div>
<div class="center"></div>
<div class="rightFence"></div>
css:
.leftFence,
.rightFence {
position: fixed;
height: 100%;
width: 52px;
background: red;
top: 0;
}
.leftFence {
left: 0;
}
.rightFence {
right: 0;
}
.center {
margin: 0 52px;
height: 100px;
background: gray;
}
Demo
#fixwidth1{
width:52px;
}
#fixwidth2{
width:52px;
}
#dynamicwidth{
width:calc(100%-104px); //i.e 100% width of browser - sum of two fixed width
background:#114455;
}
change css for boundaries div to this:
#boundaries {
overflow: hidden;
position:absolute;
top:240px;
display:block;
left:0;
right:0;
height:92px;
z-index: 15;
}
this will properly scale your entire content width to the screen resolution, nvr ever give width like width:1395px. since you made your boundaries container to be absolute, you can stretch it using its top,left,right bottom value (and also width and height);
now change your fenceleft css to this:
#fenceleft {
position: relative;
float:left;
left:0;
width:10%;
height:100%;
}
so now, for any resolution, your leftfence will always be at 0 left from the left border of its parent i.e. boundaries div. and give it a height in percentage, so that, whenever you need to adjust height, you just have to adjust the parents class, just one class.
change your fenceright css to this:
#fence {
position: relative;
height:100%;
width:80%;
float: left;
}
now notice: since you have placed float:left on the fenceleft div, fence will align next to itself i.e. 10% (width of fenceleft) away from the left border of boundaries(parent) div.
also, since it has been given a width of 80%, that means, 80%+10%(from left)=90% hence 100-90 = 10% i.e. 10% width is remaining to the right of fence div. in which you can place your fenceright
change your fenceright to this:
#fenceright {
position: relative;
left:90%;
width:10%;
height:100%;
border:Solid 1px #666666;
}
now all your divs are properly aligned, with no horizontal scroll, covering entire horizontal width of screen.
do not copy and paste these directly. organize your CSS accordingly, do the math. think about a range of resolutions and not just your screen.
read this. it shd help you out.
in the html the center div must be after the left and the right div.
<div id="boundaries">
<div id="fenceleft"><img src="" width="52" height="92" /></div>
<div id="fenceright"><img src="" width="52" height="92" /></div>
<div id="fence"></div>
</div>
in CSS margin: 0 auto let the center div fill the remainder, and width of the center div must be given.
#fence {
margin:0 auto;
background: url() repeat-x;
display: block;
height:92px;
width: 700px;
position:relative;
}
#fenceright {
position:relative;
float:right;
display: block;
width:52px;
max-width: 52px;
height:92px;
}
hi, one example, see here. i hope this can help you.