css triangle based on page height - javascript

Currently I have the situation as shown below in the snippet.
But now I want a triangle that is the same on every page. No matter how long the page is. So for example if the page is really long, then the triangle will at one point go out of the screen and there will be no more green background. (as shown here)
But the most important thing is that on every page the triangle/angle will be the same. How to do this?
$(document).ready(function() {
function waitForElement(elementPath, callBack) {
window.setTimeout(function() {
if ($(elementPath).length) {
callBack(elementPath, $(elementPath));
} else {
waitForElement(elementPath, callBack);
}
}, 300)
}
waitForElement("#leftdiv", function() {
// Initial background height set to be equal to leftdiv
$('#rightdiv').height($('#leftdiv').height());
// Initial triangle height set to be equal to leftdiv
$('#triangle').css('border-top', $('#leftdiv').height() + 'px solid transparent');
});
// When window resizes
$(window).resize(function() {
// Change height of background
$('#rightdiv').height($('#leftdiv').height());
// Change height of white triangle
$('#triangle').css('border-top', $('#leftdiv').height() + 'px solid transparent');
});
});
.container-general {
float: left;
position: relative;
background-color: black;
height: 500px;
width: 70%;
}
.background-general {
float: right;
position: relative;
/*height is set in javascript*/
width: 30%;
background-color: green;
}
#triangle {
position: absolute;
height: 0;
width: 0;
bottom: 0;
left: -1px;
border-left: 10vw solid white;
border-right: 0px solid transparent;
/*border-top is set in javascript*/
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container-general" id="leftdiv">
</div>
<div class="background-general" id="rightdiv">
<div id="triangle"></div>
</div>

You don't need JavaScript and jQuery at all for this, as long as you are willing to make minor changes to your markup:
Step 1: Update your markup
Wrap both your .container-general and .background-general with a common parent element
Use display: flex; overflow: hidden; on the parent. This has the effect of stretching the shorter background element to full height of .container-general
Step 2: Determine the fixed angle you want and set aspect ratio
Important note: If you want to keep the angle constant, you will need to know what angle you want. That will require one important trick: you want to keep .background-general the same aspect ratio in all cases, so the angle stays constant. Let's say you want it to be 60° (i.e. Math.Pi / 3): with some math, that means that the height of the .background-general should be this ratio relative to the width:
containerHeightRatioToWidth = Math.tan(Math.PI / 3) = 1.732052602783882...
There is a trick to preserve the aspect ratio: you simply set the padding-bottom of the background element. In this case, you want it to be padding-bottom: 173%); (we don't need absolute precision so we can drop the decimal points).
Here's a handy table on the height (in CSS percentages) you can use:
30deg: padding-bottom: 57%:
45deg: padding-bottom: 100%:
60deg: padding-bottom: 173%:
You can also precalculate the percentage in your browser console by pasting this:
var desiredAngleInDegrees = 60;
Math.tan(Math.PI * desiredAngleInDegrees / 180) * 100
The markup is structured as follows:
└─┬.wrapper
├──.container-general
└─┬.background-general
└─┬.background-general__background
├─::before (triangle)
└─::after (remaining fill)
To achieve the triangle effect, you have two approaches:
Step 3A: Use clip-path to trim the background element to look like a triangle
clip-path is very widely supported by modern browsers, with a notable exception for IE11 and Edge :/ This should do the trick: clip-path: polygon(100% 0, 0 0, 100% 100%);
.wrapper {
display: flex;
overflow: hidden;
}
.container-general {
background-color: black;
height: 500px;
width: 70%;
}
.background-general {
position: relative;
width: 30%;
background-color: green;
overflow: hidden;
}
.background-general__background {
position: absolute;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
/* Triangle */
.background-general__background::before {
flex-grow: 0;
content: '';
display: block;
width: 100%;
padding-bottom: 173%;
background-color: white;
clip-path: polygon(0 100%, 0 0, 100% 100%);
}
/* Extra fill */
.background-general__background::after {
flex-grow: 1;
content: '';
display: block;
background-color: white;
/* Needed to fix subpixel rendering */
margin-top: -1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<div class="container-general" id="leftdiv">
</div>
<div class="background-general" id="rightdiv">
<div class="background-general__background"></div>
</div>
</div>
Step 3B: Use an inline SVG as background image
For the greater browser compatibility, use an inline encoded SVG and stretch it to 100% width and 100% height of the parent.
We can create a simple 10×10px SVG of the following markup:
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" viewBox="0 0 10 10">
<path fill="green" d="M0,0 L10,0 L10,10 z"></path>
</svg>
Note: The preserveAspectRatio="none" is required so that we can freely stretch the SVG beyond its usual aspect ratio. For more information of how the <path>'s d attribute works, see this article: The SVG path Syntax: An Illustrated Guide
Then, all you need is to stuff this short SVG markup as data:image/svg+xml for the background image of the background container, i.e.:
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" viewBox="0 0 10 10"><path fill="green" d="M0,0 L10,0 L10,10 z"></path></svg>');
See example below:
.wrapper {
display: flex;
overflow: hidden;
}
.container-general {
background-color: black;
height: 500px;
width: 70%;
}
.background-general {
position: relative;
width: 30%;
background-color: green;
overflow: hidden;
}
.background-general__background {
position: absolute;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
/* Triangle */
.background-general__background::before {
content: '';
display: block;
flex-grow: 0;
width: 100%;
padding-bottom: 173%;
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" viewBox="0 0 10 10"><path fill="white" d="M0,0 L0,10 L10,10 z"></path></svg>');
background-size: 100% 100%;
}
/* Extra fill */
.background-general__background::after {
flex-grow: 1;
content: '';
display: block;
background-color: white;
/* Needed to fix subpixel rendering */
margin-top: -1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<div class="container-general" id="leftdiv">
</div>
<div class="background-general" id="rightdiv">
<div class="background-general__background"></div>
</div>
</div>

A simple "border triangle" bind to vw units might do:
body {
min-height: 2000px;
}
#triangle {
position: absolute;
top: 0px;
right: 0px;
border-top: 100vw solid #ff0000; /* The height of the triangle */
border-left: 30vw solid transparent; /* The width of the triangle */
}
<div id="triangle"></div>
A fiddle to play with.

Related

How to set element to grow horizontally instead of breaking to a new line?

I'm facing problem with breaking the line on website. What do I mean?
HTML code
<main class="clearfix">
<div class="first"></div>
<div class="second"></div>
<div class="third"></div>
</main>
<button>Add</button>
With such HTML code I'd like to have:
fixed height on main element (for example 80vh)
fixed height for all the elements first and third 40vh + second 80vh
fixed width for first and third element 50vw
fluid width for second element - but this is main problem - second element has to be in the same place and grow horizontally (to create scroll on the bottom of the site)
Please find my codepen
I've added button that'll add pixels to second element - but it destroys my website.
I'm not sure if flexbox is better than floats.
I'll appreciate any tip.
Here is the snippet:
let counter = 0;
document.querySelector("button").addEventListener("click", function() {
document.querySelector(".second").style.width = `calc(50% + ${counter}px)`;
console.log(counter);
counter++;
});
* {
padding: 0;
margin: 0;
}
main {
max-height: 80vh;
}
.first,
.third {
height: 40vh;
width: 50vw;
background-color: black;
float: left;
}
.third {
background-color: red;
}
.second {
height: 80vh;
width: 50%;
float: right;
background-color: blue;
}
.clearfix::after {
content: "";
display: table;
clear: both;
}
<main class="clearfix">
<div class="first"></div>
<div class="second"></div>
<div class="third"></div>
</main>
<button>Add</button>
I would suggest you to go with position properties. Since you have a little difference between the order of your DOM element and their visual representation, like 1,2,3 in the DOM, but visually it's more like 1,3,2.
However, in such situation float is your enemy. I'm not 100% sure about flex, AFAIK flex would keep all the elements inside the parent element and prevent the scrolling.
If you go with absolute positioning, (since you already have the heights and widths defined)
Apply:
position: relative to the main element, it will be the base point of the child elements if they are set to absolute.
overflow-x: scroll to the main element. it will allow you to scroll horizontally when you increase the width of your second element.
position: absolute on .first, .second, .third, as you have the height and width defined, now set their position accordingly, check the snippet, you'll get it.
Finally you're good to add more value to your width of the target element.
Tip: always keep a consistency in your css units, for example, if used vh / vw use this for similar elements at least, or if px / em / rem is used, try to use the same accordingly.
Check the snippet in full page mode
let counter = 0;
document.querySelector("button").addEventListener("click", function() {
document.querySelector(".second").style.width = `calc(50vw + ${counter}vw)`;
document.querySelector("#added").textContent = counter;
counter++;
});
* {
padding: 0;
margin: 0;
}
main {
overflow-x: scroll;
position: relative;
min-height: 80vh;
}
.first,
.third {
height: 40vh;
width: 50vw;
background-color: black;
position: absolute;
left: 0;
top: 0;
}
.third {
background-color: red;
top: 40vh;
}
.second {
height: 80vh;
width: 50vw;
background-color: blue;
position: absolute;
left: 50vw;
top: 0;
}
button {
margin: 30px 5px;
border: 1px solid #cecece;
padding: 5px 10px;
}
<main>
<div class="first"></div>
<div class="second"></div>
<div class="third"></div>
</main>
<button>Add</button>
<p><span id="added">0</span>vw Added to blue div's width</p>

Calculate div width/height when inside a zoom/scale transform

I have a div inside another div with transform scale applied.
I need to get the width of this div after the scale has been applied. The result of .width() is the original width of the element.
Please see this codepen:
https://codepen.io/anon/pen/ZMpBMP
Image of problem:
Hope this is clear enough, thank you. Code below:
HTML
<div class="outer">
<div class="inner">
</div>
</div>
CSS
.outer {
height: 250px;
width: 250px;
background-color: red;
position: relative;
overflow: hidden;
}
.inner {
background-color: green;
height: 10px;
width: 10px;
transform: translate(-50%);
position: absolute;
top: 50%;
left: 50%;
transform: scale(13.0);
}
JS
$(function() {
var width = $('.inner').width();
// I expect 130px but it returns 10px
//
// I.e. It ignores the zoom/scale
// when considering the width
console.log( width );
});
Use getBoundingClientRect()
$(function() {
var width = $('.inner')[0].getBoundingClientRect();
// I expect 130px but it returns 10px
//
// I.e. It ignores the zoom/scale
// when considering the width
console.log(width.width);
});
https://jsfiddle.net/3aezfvup/3/
i achieved your 130 by this
var x = document. getElementsByClassName('inner');
var v = x.getBoundingClientRect();
width = v.width;
You need the calculated value. This can be done in CSS.
Use calc() to calculate the width of a <div> element which could be any elements:
#div1 {
position: absolute;
left: 50px;
width: calc(100% - 100px);
border: 1px solid black;
background-color: yellow;
padding: 5px;
text-align: center;
}
I found this about this topic.
Can i use Calc inside Transform:Scale function in CSS?
For JS:
How do I retrieve an HTML element's actual width and height?

max scale in middle instead of end

In the following snippet, I am trying to achieve an effect where the div which appears in the middle of the visible scroll section is at full scale scale(1); and the other div's scale falloff towards scale(0); as they approach the edges.
I have drawn a debug box in the middle where the full scale div should appear.
var viewport = {
x: $("#scroll").scrollLeft(),
width: $("#scroll").width(),
}
$("#scroll").scroll(function() {
viewport.x = $("#scroll").scrollLeft();
recalculateScale();
});
recalculateScale();
function recalculateScale() {
$("#example > div").each(function() {
let middleOfThis = ($(this).position().left + ($(this).width() * 0.5)); // calculate from the middle of each div
let scale = Math.sin(middleOfThis / $("content").width());
$(this).css('transform', 'scale(' + scale + ')');
});
}
content {
position: relative;
display: block;
width: 500px;
height: 100px;
}
content::after {
content: '';
position: absolute;
display: block;
width: 20%;
height: 100%;
left: 50%;
top: 0;
transform: translateX(-50%);
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.5);
}
#scroll {
display: block;
width: 100%;
height: 100%;
overflow-x: scroll;
border: 1px solid #000;
}
#example {
display: block;
width: 200%;
height: 100%;
font-size: 0;
overflow: none;
}
#example>div {
display: inline-block;
width: 10%;
height: 100%;
background-color: #f00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<content>
<div id="scroll">
<section id="example">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</section>
</div>
</content>
Currently the scale is spanning from far left to right of #example. I know I need to factor the viewport dimensions into the equation before Math.sin is evaluated, I just can't get it quite right.
Note: no arrow functions because I have to target IE11.
Two issues:
While .position().left returns the rendered position of the element after scaling, .width() returns the element's width without taking the scaling into account. Obviously such different way of measurement will lead to a wrong calculation of the middle point. Use .getBoundingClientRect().width instead: that will take the current scaling into account
When using trigonometric functions, you need to make sure the argument represents an angle expressed in radians. In your code, the value ranges from 0 to 1, while the sine takes its maximum value not at 0.5, but at π/2. So you should perform a multiplication with π to get the desired result.
Here is the adapted code:
var viewport = {
x: $("#scroll").scrollLeft(),
width: $("#scroll").width(),
}
$("#scroll").scroll(function() {
viewport.x = $("#scroll").scrollLeft();
recalculateScale();
});
recalculateScale();
function recalculateScale() {
$("#example > div").each(function() {
// 1. Use different way to read the width: this will give the rendered width
// after scaling, just like the left position will be the actually rendered
// position after scaling:
let middleOfThis = $(this).position().left
+ this.getBoundingClientRect().width * 0.5;
// 2. Convert fraction to a number of radians:
let scale = Math.sin(middleOfThis / $("content").width() * Math.PI);
$(this).css('transform', 'scale(' + scale + ')');
});
}
content {
position: relative;
display: block;
width: 500px;
height: 100px;
}
content::after {
content: '';
position: absolute;
display: block;
width: 20%;
height: 100%;
left: 50%;
top: 0;
transform: translateX(-50%);
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.5);
}
#scroll {
display: block;
width: 100%;
height: 100%;
overflow-x: scroll;
border: 1px solid #000;
}
#example {
display: block;
width: 200%;
height: 100%;
font-size: 0;
overflow: none;
}
#example>div {
display: inline-block;
width: 10%;
height: 100%;
background-color: #f00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<content>
<div id="scroll">
<section id="example">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</section>
</div>
</content>
NB: Because of floating point precision limitations, the calculation of the mid points could slide away with little fractions. This will be so tiny, that it should not make a difference in actual pixel distance, but it would not hurt to pre-calculate the centres of the elements, so that you always use the same value.

Create a div with aspect ratio 1:1 knowing only its height in percentage

I was wondering if you can help me with this.
I have a div (in white) where I need to put two circular buttons (in green) on the borders. Everything should be done with CSS.
It should look like this:
Screenshot
Now, the thing is that I don't know the size of the white div, and I won't know it at the time of creation, because it will get added to the DOM afterwards. All I know is that the white div has a percentage width and height relative to its future parent. So, at the time of creation, since it's not yet added, any calls to width(), height() or its css values won't work.
I've seen all those snippets that tell you how to make a div with a fixed aspect ratio. I need this now, I need the button to be 1:1, but all I know about the dimensions, is that it has to be 100% of the height of the white div (and therefore, its width should be equal as its height). All the examples I've seen assume that you know the width and to make the height keep the ratio. In my case, what I know is the height (100%) and I want the width to adapt.
I have no idea how to achieve this.
This is my snippet:
body{
background-color: #DCDCDC;
}
.container {
width: 50%;
height: 7%;
background: white;
border-radius: 20px;
position: absolute;
}
.arrow {
background: green;
border-radius: 20px;
height: 100%;
position: absolute;
}
.arrow:after{
content: "";
display: block;
padding-right: 100%;
}
.arrow:last-child {
right: 0;
}
<div class="container">
<div class="arrow"></div>
<div class="arrow"></div>
</div>
https://jsfiddle.net/7bxecL9m/
If you know how can I do this without entering any fixed value (jQuery use is of course valid), I'd really appreciate it.
Thanks.
There are many variables here:
Since container's height is % and circle radius is px units, one is static and the other one will resize.
The only way to preserve 1:1 with just html/css, considering the container's height % will resize circle's height as well, would be to isolate circle's div width & height to something static like px units.
Now, since you said no fixed dimensions, the only thing I can think of is to comment .arrow's 100% height, to prevent resizing other than 1:1, and nesting a div inside .arrow to restrain 1:1 with static units (ideally impacting .arrow directly would be less code but if you don't want/can't set them on that element, maybe you consider this).
If you want the circle to remain circular as the content expands, you need to dynamically adjust the height to match the width. You could use Javascript to achieve this, but your border-radius is tied to container's in px static units, since container will always be bigger something like border-radius: 50% wouldn't work for both, 50% radius of circle would never match 50% of container's (that is, if you care about radius alignment).
body {
background-color: #DCDCDC;
}
body,
html {
height: 100%;
}
.container {
width: 50%;
height: 37%;
background: white;
border-radius: 20px;
position: relative;
}
.arrow {
background: green;
border-radius: 20px;
/*height: 100%;*/
position: absolute;
overflow: hidden;
}
.bLimit {
height: 40px;
width: 40px;
line-height: 40px;
}
.arrow:after {
content: "";
display: block;
padding-right: 100%;
}
.arrow:last-child {
right: 0;
}
<div class="container">
<div class="arrow">
<div class="bLimit">button overflow</div>
</div>
<div class="arrow">
<div class="bLimit">button</div>
</div>
</div>
Why not doing a fixed width in percent for your arrow :
.arrow {
background: green;
border-radius: 20px;
height: 100%;
position: absolute;
width: 10%;
}
body{
background-color: #DCDCDC;
}
.container {
width: 50%;
height: 7%;
background: white;
border-radius: 20px;
position: absolute;
}
.container:after,.container:before{
content: " ";
display: block;
padding: 4%;
z-index: 999;
top: 0;
position:absolute;
background: green;
border-radius: 50%;
}
.container:before {
left: 0;
}
.container:after{
right: 0;
}
<div class="container">
</div>
You can achieve using before and after CSS pseudo selectors. You check this Example.
There is a posibility to get this result using a image (that won't show) of the required ratio.
In this case, the ratio is 1:1 so we will use an image of 50px (but it can be any size)
.container {
width: 300px;
height: 20px;
border: solid 1px blue;
margin: 40px;
position: relative;
}
.container:nth-child(2) {
height: 40px;
}
.container:nth-child(3) {
height: 60px;
}
.arrow {
height: 100%;
background-color: red;
opacity: 0.5;
position: absolute;
border-radius: 50%;
transform: translateX(-50%);
}
.arrow:last-child {
right: 0px;
transform: translateX(50%);
}
img {
height: 100%;
opacity: 0;
}
<div class="container">
<div class="arrow">
<img src="https://placehold.it/50x50">
</div>
<div class="arrow">
<img src="https://placehold.it/50x50">
</div>
</div>
<div class="container">
<div class="arrow">
<img src="https://placehold.it/50x50">
</div>
<div class="arrow">
<img src="https://placehold.it/50x50">
</div>
</div>
<div class="container">
<div class="arrow">
<img src="https://placehold.it/50x50">
</div>
<div class="arrow">
<img src="https://placehold.it/50x50">
</div>
</div>

Is it possible to fill an icon to a percentage? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I was wondering if there is a way to fill a specific icon or sprite to a designated percentage - i.e. 20% or something like that. I am trying to create a responsive shape or image that will serve as fluid chart, of sorts. I know the below is not a great example - the svg is also in font form. I want to dynamically fill this image to a specified % in my code.
So let's say a data point reads 20%, I want the heart to fill with another color (e.g. color:#DA1C5C) up to 20%, leaving the rest the original color. The code I'm working with is using a straight icon font and not the image svg, but it's not hosted yet.
<div class="icon">
<i class="icon-doubleheart">
<img src="https://s3.amazonaws.com/yourcareassets/doubleheart.svg">
</i>
With SVG: fiddle
HTML:
<div class="icon">
<div id='blackIcon' class="icon-doubleheart">
<img src="https://s3.amazonaws.com/yourcareassets/doubleheart.svg"/>
</div>
<div id='holdci'>
<div id='colorIcon' class="icon-doubleheart">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 500 500" enable-background="new 0 0 500 500" xml:space="preserve">
<g>
<path class='newColor' d="M353.1,137c-37.2-17.2-85.9-1-103.1,36.1c-17.2-37.1-65.9-53.3-103.1-36.1c-27.5,12.7-45,39.2-42.7,72.8h0.2 c1.4,14.1,6.1,29.4,15.2,45.5c22.2,39.4,61.6,69.1,130.3,122.3c68.7-53.2,108.1-82.9,130.3-122.3c9.1-16,13.8-31.3,15.2-45.5h0.2 C398,176.2,380.5,149.7,353.1,137z"/>
<path class='newColor' d="M493.5,124c-11.1-34.6-36.2-62.5-70.5-78.6c-18.8-8.8-40-13.4-61.4-13.4c-45.8,0-87.4,20.7-111.6,54.2 c-24.2-33.5-65.8-54.3-111.6-54.3c-21.3,0-42.6,4.6-61.4,13.4c-34.4,16-59.4,44-70.6,78.6C0,144.3-3.9,173.4,6,209.7h0.7 c4.3,14.9,10.8,31,20.4,48.2c36.1,64.4,99.1,113.5,203.5,194.8l19.4,15.1l19.5-15.2C373.9,371.4,436.9,322.3,472.9,258 c9.7-17.2,16.2-33.3,20.4-48.2h0.7C503.9,173.4,500,144.3,493.5,124z M468.8,207.2h-0.7c-4,12.6-9.6,25.5-16.9,38.6 c-33.6,60-95.1,107.9-197,187.3l-4.2,3.3l-4.1-3.2C144,353.7,82.4,305.8,48.8,245.8c-7.3-13-13-25.9-16.9-38.5h-0.7 c-8-26.8-8.4-52.4-1-75.5c9-28,29.4-50.6,57.4-63.7c15.6-7.3,33.2-11.1,50.9-11.1c44.3,0,83.7,23.2,100.3,59.1l11.3,24.5l11.3-24.5 C277.9,80.2,317.2,57,361.6,57c17.7,0,35.3,3.8,50.9,11.1c28,13.1,48.4,35.7,57.3,63.6C477.2,154.8,476.8,180.4,468.8,207.2z"/>
</g>
</svg>
</div>
</div>
</div>
CSS:
.icon {
width: 10em;
height: 10em;
}
#blackIcon {
width: 100%;
height: 100%;
}
#holdci {
margin-top: -100%;
overflow: hidden;
width: 0;
height: 99%;
}
#colorIcon {
width: 10em;
height: 10em;
}
.newColor {
fill: #DA1C5C;
}
JS:
var fill = 0;
var update = setInterval(function() {
fill += 1;
if (fill <= 100) {
$('#holdci').css('width', (fill+'%'));
} else {
clearInterval(update);
}
}, 100);
With pure CSS:
HTML:
<div id='Icon'>
<div id='IconText'>f</div>
<div id='fillIcon'></div>
</div>
CSS:
#Icon {
position: absolute;
width: 2em;
height: 2em;
border: 0.125em solid blue;
border-radius: 0.2em;
}
#fillIcon {
position: absolute;
z-index: 0;
width: 100%;
height: 0;
margin-top: 100%;
background-color: blue;
}
#IconText {
position: absolute;
z-index: 1;
width: 100%;
height: 100%;
line-height: 150%;
text-align: center;
color: #cccccc;
font-weight: bold;
font-family: consolas;
font-size: 1.5em;
}
JS:
var fill = 0;
var update = setInterval(function() {
fill += 1;
$('#fillIcon').css('height', (fill+'%'));
$('#fillIcon').css('margin-top', ((100 - fill)+'%'));
if (fill === 100) {
clearInterval(update);
}
}, 100);
With an image: fiddle
HTML:
<div id='Icon'>
<div id='IconText'><img style='width: 100%; height: 100%;' src='http://bellybusting.com.au/wp-content/uploads/2014/03/fb.jpg'/></div>
<div id='fillIcon'><img style='width: 2em; height: 2em;' src='http://getdesign.org/wp-content/uploads/2013/08/Facebook-icon-with-green-background-56.png'/></div>
</div>
CSS:
#Icon {
position: absolute;
width: 2em;
height: 2em;
}
#fillIcon {
position: absolute;
z-index: 2;
width: 100%;
height: 0%;
margin-top: 0;
overflow: hidden;
}
#IconText {
position: absolute;
z-index: 1;
width: 100%;
height: 100%;
line-height: 150%;
text-align: center;
color: #cccccc;
font-weight: bold;
font-family: consolas;
font-size: 1.5em;
}
JS:
var fill = 0;
var update = setInterval(function() {
fill += 1;
$('#fillIcon').css('height', (fill+'%'));
//$('#fillIcon').css('margin-top', ((100 - fill)+'%'));
if (fill === 100) {
clearInterval(update);
}
}, 100);
You can, here's 2 methods for your example of 20% width:
Method 1: HTML image
HTML:
<div>
<img src="myImage.jpg" width="135" height="155" class="responsiveImage">
</div>
And the CSS:
div {
max-width:100%;
width:20%;
}
img.responsiveImage {
width:100%;
max-width:100%;
height:auto /* only necessary to override the 'Height' attribute if imcluded */
margin:0 auto;
}
The results will be a scaleable hardcoded image. You can check out the Fiddle here.
If you want to use CSS for more control, you can use this instead:
Method 2: CSS background image
HTML:
And CSS, based on this helpful answer:
div.responsiveImage {
width:20%;
padding:12% 0; /* The 20:24 ratio of width to combined padding matches the dimensions of the image */
background: url(myImage.jpg) no-repeat top left;
background-position:50% 50%; /* Sets reference point to scale from */
background-size:cover;
border:solid 1px red;
}
Here's the fiddle of it in action.
The width and top and bottom padding is calculated by the ratio of width:height of the image you want to use. In the Fiddle examples, I've used one that is 135px wide by 155px high. To obtain the ratio, I used this:
(155/135)*100 = 114.814
This means the height is 114% the value of the width. Hence, if the width = 20%, the height is (20 * 114814)/100, or 23%. In my case, I split this into 2 by applying this equally as top and bottom padding (As monitors can't display half a pixel, I rounded it up).
Bear in mind that the padding value for the height of the image will change once it has a wrapper around it. Also, the overall height of the container will change if any content is added.

Categories

Resources