I have an image inside a container. The image should always be at full browser width (100vw). As my layout is responsive, and the container has a fixed width at a certain point (45em), I can't simply use negative margins. So I got an idea, but as a novice I can't seem to achieve it...
This is what I want to do:
Check the body width
Check the container width
Subtract the element width from the body width
Divide this number in two
Add this number as a negative margin to an element
This is what I got so far...
var bodyWidth = $('body').width(); //Check the body width
var elemWidth = $('#content').width(); //Check the container width
var margin = bodyWidth-elemWidth; //Subtract the element width from the body width
I still need to divide the number in two, and add this number as a negative margin to an element.
Help is much appreciated.
You're on the right track.
var bodyWidth = $('body').width(); //Check the body width
var elemWidth = $('#content').width(); //Check the container width
var margin = bodyWidth-elemWidth; //Subtract the element width from the body width
var dividedMargin = margin / 2; // Divide the margin by 2
var negativeMargin = dividedMargin * -1; // set number to negative number
$(element).css("margin", negativeMargin); // replace element by the element name you want to apply this to.
You can also replace margin by margin-left, margin-right,margin-top or margin-bottom.
Related
Say I have a container which height is calculated by it's width. Width changes dynamically base on the viewport width of the screen. I want to detect when the height has reached 70vh or any number and if the limit has reached I want to get it's width. That has to happen dynamically base on the viewport width and height. For instance, I load the page and the height has reached 70vh and when it reached 70vh, it's width is say 1072px. I want to do that dynamically. Does any one know any formula to do that??
You can use this in your script file it will print your screen dimensions for you
const width = window.innerWidth || document.documentElement.clientWidth ||
document.body.clientWidth;
const height = window.innerHeight|| document.documentElement.clientHeight||
document.body.clientHeight;
console.log(width);
console.log(height)
document.write("The Height is " + height + "px ")
document.write("The width is  " + width + "px")
I found the following code used to track the scroll percentage as you scroll down the page.
document.addEventListener('scroll', function(){
var h = document.documentElement,
b = document.body,
st = 'scrollTop',
sh = 'scrollHeight';
var percent = (h[st]||b[st]) / ((h[sh]||b[sh]) - h.clientHeight) * 100;
document.getElementById('scroll').textContent = 'scrolled: ' + percent + '%';
});
That shows the percentage of the whole page. If I only want the scroll percentage of a specific div like this example https://www.thefarmersdog.com/ how the dog bowl scrolls over when you move down the page.
You need to use getBoundingClientRect()
const coordinates = document.getElementById('your-id').getBoundingClientRect();
console.log(coordinates.top); // This is the distance to the top of the screen
Here is a detailed article that you can read if you need more info.
Divide number of pixels that an element's content has been scrolled vertically by the height of an element's content minus an element's offset height and multiply by 100 to get percentage value from 0 to 100. Optionally, round it to get an integer value.
scrollPercent = scrollTop / (scrollHeight - offsetHeight)
const scrollLabelElement = document.getElementById('scroll');
element.addEventListener('scroll', (_event) =>
const percentScrolled = Math.round(element.scrollTop / (element.scrollHeight - element.offsetHeight));
scrollLabelElement.textContent = `Scrolled: ${percentScrolled}%`;
});
Lately I am fiddling a bit in React and I have encountered the following problem, which is not necessarily React related but more Javascript / CSS in general related.
I have created a bar which contains a certain amount of cells. These cells all have the same width and height properties but will adjust its width/height properties to the viewport.
When I click one of these cells a div get's appended to the container of the cells, this div is an overlay with a different color (so you know which cell has been clicked).
The problem is that the bar and it's containing cells have their width attribute set in percentage, this has been done so I can calculate the width needed based on the total cell count when adding more cells to the containing div.
The overlay div however, which is added when a cell is being clicked, has it's width defined in px. This is because the left and top position of the overlay div is being determined with the pageY and pageX coordinates and the height and width of the cell element is being fetched with offsetHeight and offsetWidth.
The result of the above is that the actual width of the cell is a decimal value (it is percentage) but the calculated width is a rounded px value, this results in the following:
The normal Cell width:
The Overlay div width:
as you can see this is a minor difference in width, to show it properly I had to zoom in quite a bit. In the second picture you see that how further in left position the overlay div is being added, the bigger the difference (which is logical).
The code:
This is the normal Cell which is being rendered
_onRenderCell = (item, index) => {
this.myCell = React.createRef();
return (
<div
className="ms-ListGridExample-tile"
data-is-focusable={false}
style={{
width: 100 / this._columnCount + '%',
height: this._rowHeight * 1.5,
float: 'left'
}}
>
... rest of the rendering omitted ...
You can see here that the width is determined based on the column count and returned as a percentage: width: 100 / this._columnCount + '%'
The onMouseDown event to add the overlay div:
_onMouseDown (e){
const containerNode = this.rsvnRef.current;
const cellNode = this.myCell.current;
// Determine current position
let posY = e.pageY - containerNode.getBoundingClientRect().top;
let posX = e.pageX - containerNode.getBoundingClientRect().left;
// Determine width and height of cell
let height = cellNode.offsetHeight;
let width = cellNode.offsetWidth;
// Determine top and left positions
let top = posY - (posY % height);
let left = posX - (posX % width);
var reservationClasses = document.getElementsByClassName('reservation');
var collisions = Array.prototype.filter.call(reservationClasses, function(rsv) {
return rsv.offsetTop == top && rsv.offsetLeft == left;
});
if (collisions.length == 0){
// Creating the overlay div
const newRsvn = document.createElement("div");
newRsvn.className = "reservation reservation-creating";
newRsvn.style.top = top + 'px';
newRsvn.style.left = left + 'px';
newRsvn.style.height = height + 'px';
newRsvn.style.width = width + 'px';
// Apending overlay div to container
containerNode.append(newRsvn);
}
}
My question is (as you probably expected); how can I make the overlaying div have the exact same width as the cell div? Can you return the offsetWidth with decimal places, or can I in some way calculate the offsetWidth in percentage?
After some more research, and thanks to this post: Converting width from percentage to pixels I managed to get it done.
However, I don't know if it is the best / right solution so please do give feedback if you think there is a better way!
I decided to just set the width of the cell in pixels instead of a percentage. The rendering of a cell is being done dynamically anyway (each time the screen size changes) so calculating the right amount of pixels in the cell rendering and rounding that to a whole number works fine since now both the cell and overlaying div are using the same width.
The code:
_onRenderCell = (item, index) => {
this.myCell = React.createRef();
const containerNode = this.rsvnRef.current;
let percents = parseInt(100 / this._columnCount);
let parentWidth = parseInt(containerNode.offsetWidth);
let pixels = parseInt(parentWidth*(percents/100));
return (
<div
className="ms-ListGridExample-tile"
data-is-focusable={false}
style={{
// width: 100 / this._columnCount + '%',
width: pixels + 'px',
height: this._rowHeight * 1.5,
float: 'left'
}}
>
... rest of the rendering omitted ...
I am trying to make a custom scrollbar using the following method:
Scrollbar height is inversely proportional to content height.
scrollHeight ∝ 1 / contentHeight.
scrollHeight = k / contentHeight
So if we take constant of k 's value as 10000. (As the height of container of content is 100px and 100 times 100 is 10000). It's still not doing the job.
Can't figure out the problem. If words are confusing check out this JS Fiddle. I know the concept just can't figure out how to set the height of the scroller for dynamic content.
You can try this:
$(document).ready(function(e){
$('#scroll').draggable({
axis: 'y',
containment: 'parent'
});
var contentHeight = $('p').height();
$('.hey').html(contentHeight);
var containerHeight = $('#scroll-cont').height();
var k = 10000;
var scrollerHeight = $('#scroll').height((k / contentHeight) / 2);
$('.hey').append('<br>' + $('#scroll').height());
$(document).mousemove(function(e){
var offsetS = $('#scroll').offset().top * 2;
$('#scroll-cont').scrollTop(offsetS);
});
});
scrollbarHeight / scrolltrackHeight = visibleHeight / contentHeight
scrollbarHeight = scrolltrackHeight * visibleHeight / contentHeight
For example, you content's height 1000px, and visible height is 250px. If your scrolltrack height is 240px (all visible space - 5px padding from top/bottom), then your scrollbar should be 240 * 250 / 1000 = 60
So i have a gallery where most my images are currently controlled 100% by CSS. However, in setting min-height: 100%; on my images, i cause some to stretch. I don't have too many problematic photos, but it's out of my control what the user will upload.
Is there anyway with jQuery i can get image height and check if it's meeting a requirement, and if not, somehow increase the image width in order to meet the height requirement but keep things all in ratio? So i therefore avoid causing any distortion but keep the gallery neat by having divs without gaps.
Note: The image provided is what happens when i remove my min-height: 100%; so that you can see my issue.
Update - - - - -
I found a solution that seems to work ok for the moment, it might not be the best attempt but i found another answer that helped me: How to resize images proportionally / keeping the aspect ratio?
I simply tweaked the code ever so slightly, now if an image doesn't meet the minHeight required it will resize the image in proportion so until the minHeight is then reached. Seems work fine for me in testing.
**Update Final *********
After playing around i took a small snippit from the thumb script, just the part where it absolutely positions the images within the container.
$(window).load(function() {
$('.thumbnail img').each(function() {
var maxWidth = 320; // Max width for the image
var minHeight = 270; // Max height for the image
var ratio = 0; // Used for aspect ratio
var width = $(this).width(); // Current image width
var height = $(this).height(); // Current image height
if(width > maxWidth){
ratio = maxWidth / width; // get ratio for scaling image
$(this).css("width", maxWidth); // Set new width
$(this).css("height", height * ratio); // Scale height based on ratio
height = height * ratio; // Reset height to match scaled image
width = width * ratio; // Reset width to match scaled image
}
// Check if current height is larger than max
if(height < minHeight){
ratio = minHeight / height; // get ratio for scaling image
$(this).css("height", minHeight); // Set new height
$(this).css("width", width * ratio); // Scale width based on ratio
width = width * ratio; // Reset width to match scaled image
}
var $img = $(this),
css = {
position: 'absolute',
marginLeft: '-' + ( parseInt( $img.css('width') ) / 2 ) + 'px',
left: '50%',
top: '50%',
marginTop: '-' + ( parseInt( $img.css('height') ) / 2 ) + 'px'
};
$img.css( css );
});
});
This loops through all my thumbnails, resizes them accordingly. So if the minimum height is not met, the image will be scaled up until the height fits my thumbnail container. Then the bottom part will take take each image, absolutely position it, and take the width and height and divide by 2, in order to work out how much to minus off on the margins to center the image. I'm still tweaking this, but seems to work well for me at the moment. I hope this helps someone else.
Alternatively
Anyone with a similar issue i found this: http://joanpiedra.com/jquery/thumbs/ I had begun writing my own to do exactly this, but im going to look into how well this works and adapt it as needed.
I found a solution that seems to work ok for the moment, it might not be the best attempt but i found another answer that helped me: How to resize images proportionally / keeping the aspect ratio?
Updated question with my findings
$(window).load(function() {
$('.image-gallery-item-image-link img').each(function() {
var maxWidth = 320; // Max width for the image
var minHeight = 270; // Max height for the image
var ratio = 0; // Used for aspect ratio
var width = $(this).width(); // Current image width
var height = $(this).height(); // Current image height
if(width > maxWidth){
ratio = maxWidth / width; // get ratio for scaling image
$(this).css("width", maxWidth); // Set new width
$(this).css("height", height * ratio); // Scale height based on ratio
height = height * ratio; // Reset height to match scaled image
width = width * ratio; // Reset width to match scaled image
}
// Check if current height is larger than max
if(height < minHeight){
ratio = minHeight / height; // get ratio for scaling image
$(this).css("height", minHeight); // Set new height
$(this).css("width", width * ratio); // Scale width based on ratio
width = width * ratio; // Reset width to match scaled image
}
var $img = $(this),
css = {
position: 'absolute',
marginLeft: '-' + ( parseInt( $img.css('width') ) / 2 ) + 'px',
left: '50%',
top: '50%',
marginTop: '-' + ( parseInt( $img.css('height') ) / 2 ) + 'px'
};
$img.css( css );
});
});
well, if keeping the entire picture visible isn't necessary(e.g. thumbnails in a gallery), you could accomplish this with css only. it seems you have landscape type photos.
html
<div class="img-container">
<img src="path/to/img.png" alt="">
</div>
css:
div > img {
background-repeat: no-repeat;
background-position: center center;
background-attachment: fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
width:100%;
height:100%;
}
jquery:
$(document).ready(function(){
$(".imgcontainer > img").each(function(){
var thisimg = "url("+$(this).attr('src')+")";
$(this).css({'background-image': thisimg });
$(this).attr('src', '');
});
});
Whose aspect ratio you are talking about ? aspect ratio of your gallery or the aspect ratio of the image ? You can't keep an image in correct aspect ratio by changing one dimension only (here height). In order to keep aspect ratio, you must change both the height and width of the image. Any way if you want try this :
var img = document.getElementById('imageid');
var width = img.clientWidth;
var height = img.clientHeight;
if(width >height)
$(img).attr('style',"width=100%");
else
$(img).attr('style',"height=100%");
What I am trying to do is that, set the css of the largest dimension to 100%. It'll do the trick.
So, I realize this question asked a while ago. But I've since found a sweet css only way to maintain the aspect ratio of an element, fluidly. Try it out:
#targetElement {
max-width: 100%;
}
#targetElement:after {
content: '';
width: 100%;
padding-bottom: <aspect-ratio>%; // where (height / width)*100 = <aspect-ratio>
}
Yeah, so I use this trick all the time now, and it's definitely more performant and less verbose than using javascript, or even less efficient, JQuery. Hope this helps somebody somewhere! If you're a LESS person, I have a mixin Gist on Github that does this -- that's how often I use it! It lives here: Sweet AR trick.