Changing body tag style through JavaScript - javascript

I'm trying to write a script to change the width of the page, considering user's client width.
It's something like this:
function adjustWidth() {
width = 0;
if (window.innerHeight) {
width = window.innerWidth;
} else if (document.documentElement && document.documentElement.clientHeight) {
width = document.documentElement.clientWidth;
} else if (document.body) {
width = document.body.clientWidth;
}
if (width < 1152) {
document.getElementsByTagName("body").style.width="950px";
}
if (width >= 1152) {
document.getElementsByTagName("body").style.width="1075px";
}
}
window.onresize = function() {
adjustWidth();
};
window.onload = function() {
adjustWidth();
};
With this script I get an error from Firebug:
document.getElementsByTagName("body").style is undefined
Now my question is, how can i access the style of body? Because in the css sheet its selector and width property are defined.

That function returns a list of nodes, even though there's only one <body>.
document.getElementsByTagName("body")[0].style = ...
Now, that said, you may want to look into doing this with CSS instead of JavaScript. With CSS media queries, you make such adjustments:
#media screen and (max-width: 1151px) {
body { width: 950px; }
}
#media screen and (min-width: 1152px) {
body { width: 1075px; }
}
Media queries work in IE9 and pretty much all other modern browsers. For IE8 you can fall back to JavaScript or just let the body be 100% of the viewport width or something.

document.getElementsByTagName("body")[0].style

document.getElementsByTagName('body')[0].style = 'your code';
Example:
document.getElementsByTagName('body')[0].style = 'margin-top: -70px';

getElementsByTagName returns an array of nodes so you must use [] to access elements.
Try document.getElementsByTagName("body")[0].style

I believe what you get back from document.getElementsByTagName("body") is HTMLCollection. You should be able to use document.getElementsByTagName("body")[0].style to get what you want.

As noted in comments (but strangely still missing among the answers), it should actually be document.body.style. For example, document.body.style.backgroundColor = "#3f3f3f";

Related

Issue changing javascript function based on media query with event handler

Sorry if this is a basic question. I mainly work with design and am not entirely comfortable with JavaScript.
I have a navigation menu which is prompted to display when clicking an SVG using an Event Listener. Based on the size of the screen on which the menu is being displayed I would like to change the function to a function stating a different height for the navigation on click. This way smaller devices will have a certain height navigation, and larger will have a different height as well.
Here is the code as far as I have dabbled into it
// media query event handler
if (matchMedia) {
const mq = window.matchMedia("(min-width: 500px)");
mq.addListener(WidthChange);
WidthChange(mq);
}
// media query change
function WidthChange(mq) {
if (mq.matches) {
// at least 500px
document.getElementById("onclick").addEventListener("click", menuSize);
function menuSize() {
document.getElementById("mobilemenu").style.height = "35%";
document.getElementById("mobilemenu").style.opacity = "1";
document.getElementById("movbilenav").style.opacity = "0";
}
} else {
// less than 500px
document.getElementById("onclick").addEventListener("click", menusizeL);
function menusizeL() {
document.getElementById("mobilemenu").style.height = "50%";
document.getElementById("mobilemenu").style.opacity = "1";
document.getElementById("movbilenav").style.opacity = "0";
}
}
}
As of now I get no response at all when clicking the navigation menu. Thank you, and sorry if this is a rudimentary question.
I think you should convert your solution to mainly use css. Generally, the more you can solve with css instead of js, the more the browser will take care of everything and keep everything smooth.
You can just add a media query in your stylesheets to handle the height differences. To hide/show your menu, I'd rely on just adding a class via your js. Sample stylesheet:
#mobilemenu {
height: 50%;
opacity: 0;
}
#mobilmenu.showing {
opacity: 1;
}
#media (min-width: 500px) {
#mobilemenu {
height: 35%;
}
}
Then you can just add your class via js:
document.getElementById('menuopener').addEventListener('click', function() {
document.getElementById('mobilemenu').classList.toggle('showing');
});

Detect dynamic media queries with JavaScript without hardcoding the breakpoint widths in the script?

I've been searching for a lightweight, flexible, cross-browser solution for accessing CSS Media Queries in JavaScript, without the CSS breakpoints being repeated in the JavaScript code.
CSS-tricks posted a CSS3 animations-based solution, which seemed to nail it, however it recommends using Enquire.js instead.
Enquire.js seems to still require the Media Query sizes to be hardcoded in the script, e.g.
enquire.register("screen and (max-width:45em)", { // do stuff }
The Problem
All solutions so far for accessing Media Queries in Javascript seem to rely on the breakpoint being hardcoded in the script. How can a breakpoint be accessed in a way that allows it to be defined only in CSS, without relying on .on('resize')?
Attempted solution
I've made my own version that works in IE9+, using a hidden element that uses the :content property to add whatever I want when a Query fires (same starting point as ZeroSixThree's solution):
HTML
<body>
<p>Page content</p>
<span id="mobile-test"></span>
</body>
CSS
#mobile-test {
display:none;
content: 'mq-small';
}
#media screen only and (min-width: 25em) {
#mobile-test {
content: 'mq-medium';
}
}
#media screen only and (min-width: 40em) {
#mobile-test {
content: 'mq-large';
}
}
JavaScript using jQuery
// Allow resizing to be assessed only after a delay, to avoid constant firing on resize.
var resize;
window.onresize = function() {
clearTimeout(resize);
// Call 'onResize' function after a set delay
resize = setTimeout(detectMediaQuery, 100);
};
// Collect the value of the 'content' property as a string, stripping the quotation marks
function detectMediaQuery() {
return $('#mobile-test').css('content').replace(/"/g, '');
}
// Finally, use the function to detect the current media query, irrespective of it's breakpoint value
$(window).on('resize load', function() {
if (detectMediaQuery() === 'mq-small') {
// Do stuff for small screens etc
}
});
This way, the Media Query's breakpoint is handled entirely with CSS. No need to update the script if you change your breakpoints. How can this be done?
try this
const mq = window.matchMedia( "(min-width: 500px)" );
The matches property returns true or false depending on the query result, e.g.
if (mq.matches) {
// window width is at least 500px
} else {
// window width is less than 500px
}
You can also add an event listener which fires when a change is detected:
// media query event handler
if (matchMedia) {
const mq = window.matchMedia("(min-width: 500px)");
mq.addListener(WidthChange);
WidthChange(mq);
}
// media query change
function WidthChange(mq) {
if (mq.matches) {
// window width is at least 500px
} else {
// window width is less than 500px
}
}
See this post from expert David Walsh Device State Detection with CSS Media Queries and JavaScript:
CSS
.state-indicator {
position: absolute;
top: -999em;
left: -999em;
}
.state-indicator:before { content: 'desktop'; }
/* small desktop */
#media all and (max-width: 1200px) {
.state-indicator:before { content: 'small-desktop'; }
}
/* tablet */
#media all and (max-width: 1024px) {
.state-indicator:before { content: 'tablet'; }
}
/* mobile phone */
#media all and (max-width: 768px) {
.state-indicator:before { content: 'mobile'; }
}
JS
var state = window.getComputedStyle(
document.querySelector('.state-indicator'), ':before'
).getPropertyValue('content')
Also, this is a clever solution from the javascript guru Nicholas C. Zakas:
// Test a media query.
// Example: if (isMedia("screen and (max-width:800px)"){}
// Copyright 2011 Nicholas C. Zakas. All rights reserved.
// Licensed under BSD License.
var isMedia = (function () {
var div;
return function (query) {
//if the <div> doesn't exist, create it and make sure it's hidden
if (!div) {
div = document.createElement("div");
div.id = "ncz1";
div.style.cssText = "position:absolute;top:-1000px";
document.body.insertBefore(div, document.body.firstChild);
}
div.innerHTML = "_<style media=\"" + query + "\"> #ncz1 { width: 1px; }</style>";
div.removeChild(div.firstChild);
return div.offsetWidth == 1;
};
})();
I managed to get the breakpoint values by creating width rules for invisible elements.
HTML:
<div class="secret-media-breakpoints">
<span class="xs"></span>
<span class="tiny"></span>
<span class="sm"></span>
<span class="md"></span>
<span class="lg"></span>
<span class="xl"></span>
</div>
CSS:
$grid-breakpoints: (
xs: 0,
tiny: 366px,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
);
.secret-media-breakpoints {
display: none;
#each $break, $value in $grid-breakpoints {
.#{$break} {
width: $value;
}
}
}
JavaScript:
app.breakpoints = {};
$('.secret-media-breakpoints').children().each((index, item) => {
app.breakpoints[item.className] = $(item).css('width');
});
I found an hackish but easy solution :
#media (min-width: 800px) {
.myClass{
transition-property: customNS-myProp;
}
this css property is just a markup to be able to know in JS if the breaking point was reached. According to the specs, transition-property can contain anything and is supported by IE (see https://developer.mozilla.org/en-US/docs/Web/CSS/transition-property and https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident).
Then just check in js if transition-property has the value. For instance with JQuery in TS :
const elements: JQuery= $( ".myClass" );
$.each( elements, function (index, element) {
const $element = $( element );
const transition = $element.css( "transition-property" );
if (transition == "custNS-myProp") {
// handling ...
}
});
Of course there is a word of warning in the wiki that the domain of css property identifiers is evolving but I guess if you prefix the value (for instance here with customNS), you can avoid clashes for good.
In the future, when IE supports them, use custom properties instead of transition-property
https://developer.mozilla.org/en-US/docs/Web/CSS/--*.

jQuery image resizing issue

I've found this line of code somewhere using firebug and I know you need to put something where I've put the 3... behind parseFloat, but I have no idea what.
It works when I fill in a random number but the width is never the correct one and want to use it on several pages with photographs so it's always the correct size.
script type="text/javascript">
var badBrowser = (/MSIE ((5\.5)|6)/.test(navigator.userAgent) && navigator.platform == "Win32");
$(document).ready(function(){
var scaledwidth = ((parseFloat(...)*($(window).height()/4000))+50).toFixed(0);
if (badBrowser) {
$('#container img').css('height',$(window).height()+'px');
}
$('#container').css('width',scaledwidth+'px');
imageresize();
});
jQuery(window).resize(function() {
var scaledwidth = ((parseFloat(...)*($(window).height()/4000))+50).toFixed(0);
if (badBrowser) {
$('#container img').css('height',$(window).height()+'px');
}
$('#container').css('width',scaledwidth+'px');
imageresize();
});
function imageresize() {
var height = $(window).height();
if ((height) > 1340){
var quality='1440';
} else if((height) > 980) {
var quality='1080';
} else if((height) > 680) {
var quality='720';
} else if((height) > 480) {
var quality='640';
} else {
var quality='320';
}
}
</script>
Thanks in advance!
It looks to me like the value you need to put there depends on the sum of the widths of all the images; so you can't just pick a value that works for all pages.
On the other hand, it also seems like a bad solution to the problem of keeping the images next to each other. Why set the width of the container? If you just ensure white-space doesn't wrap then all the images should sit next to each other without worrying about the container's width.
#container
{
white-space: nowrap; /* keep images on the same line */
font-size: 0; /* removes whitespace between images */
}
http://jsfiddle.net/f8y4Z/
From the javascript, we now only need the imageresize() (provided we use it to set different quality source images), and trigger it on ready and resize; no magic numbers required.
(For backwards compatibility with browsers that don't or poorly support white-space, you could use <nobr></nobr>)

fix div width #media fix for IE

I have a div set to 100% width, and when the page is being looked at 1024 resolution the width should change from 100% to 1000px, I got it working properly with #media queries and works fine on FF, safari chrome. But ie8 and below ignores it, is there any other to try to get the div to change the width from 100% to 1000px at 1024 resolution on IE?
I tried this with jquery but doesn't work.
$(document).ready(function(){
if ($(window).width() < 1024) {
$('#content')css('width','1000px')
} else {
$('#content')css('width','100%')
};
}
media queries are CSS3. Means not supported by IE8 and lower. But take a look here, that brings support for media queries to IE.
$(document).load($(window).bind("resize", changeWidth));
function changeWidth( e ) {
if($(window).width()<1024)
{
$('#content').css('width','1000px');
} else {
$('#content').css('width','100%');
}
}
jsFiddle
Why not just set this in CSS:
width: 100%;
max-width: 1000px;
It's infinitely more efficient than any JS/jQuery solution, I can assure you.
you can use this code :
$(window).resize(function () {
var width = screen.width;
var height = screen.height;
if (width <= 1024) {
//somecode
} else {
//somecode
}
});
however,as Sven Bieder mentioned CSS Media Queries are better than for Responsive Design.

CSS media queries and jQuery window .width() do not match

For a responsive template, I have a media query in my CSS:
#media screen and (max-width: 960px) {
body{
/* something */
background: red;
}
}
And, I made a jQuery function on resize to log the width:
$(window).resize( function() {
console.log( $(window).width() );
console.log( $(document).width() ); /* same result */
/* something for my js navigation */
}
And there a difference with CSS detection and JS result, I have this meta:
<meta content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, width=device-width" name="viewport"/>
I suppose it's due to the scrollbar (15 px). How can I do this better?
You're correct about the scroll bar, it's because the CSS is using the device width, but the JS is using the document width.
What you need to do is measure the viewport width in your JS code instead of using the jQuery width function.
This code is from http://andylangton.co.uk/articles/javascript/get-viewport-size-javascript/
function viewport() {
var e = window, a = 'inner';
if (!('innerWidth' in window )) {
a = 'client';
e = document.documentElement || document.body;
}
return { width : e[ a+'Width' ] , height : e[ a+'Height' ] };
}
I found following code on http://www.w3schools.com/js/js_window.asp:
var w=window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
Practically its working the same way as the answer in #Michael Bird's answer, but it's more easy to read.
Edit: I was looking for a method to give exactly the same width as it is used for css media queries. But the suggested one does not work perfect on Safari with scrollbars, sorry. I ended up using modernizr.js in one central function and in the rest of the code I just check if display type is mobile, tablet or desktop. As I am not interested in the width, this works fine for me:
getDisplayType = function () {
if (Modernizr.mq('(min-width: 768px)')){
return 'desktop';
}
else if (Modernizr.mq('(min-width: 480px)')){
return 'tablet'
}
return 'mobile';
};
window.innerWidth is what you need.
if (window.innerWidth < 768) works for 768 break point in CSS
Workaround that always works and is synced with CSS media queries.
Add a div to body
<body>
...
<div class='check-media'></div>
...
</body>
Add style and change them by entering into specific media query
.check-media{
display:none;
width:0;
}
#media screen and (max-width: 768px) {
.check-media{
width:768px;
}
...
}
Then in JS check style that you are changing by entering into media query
if($('.check-media').width() == 768){
console.log('You are in (max-width: 768px)');
}else{
console.log('You are out of (max-width: 768px)');
}
So generally you can check any style that is being changed by entering into specific media query.
My experience was that the media query width tracks document.body.clientWidth. Because of a vertical scroll bar coming and going, checking document, window, or viewport().width could cause my Javascript to run late--after the media query rule change, depending on the height of the window.
Checking document.body.clientWidth allowed my script code to execute consistently at the same time the media query rule took effect.
#media (min-width:873px) {
//some rules
}
...
if ( document.body.clientWidth >= 873) {
// some code
}
The Andy Langton code put me onto this--thanks!
Hi i use this little trick to get JS and CSS work together easily on responsive pages :
Test the visibility of an element displayed or not on CSS #media size condition.
Using bootstrap CSS i test visibility of a hidden-xs class element
var msg = "a message for U";
/* At window load check initial size */
if ( $('#test-xsmall').is(':hidden') ) {
/* This is a CSS Xsmall situation ! */
msg = "#media CSS < 768px. JS width = " + $(window).width() + " red ! ";
$('.redthing-on-xsmall').addClass('redthing').html(msg);
} else {
/* > 768px according to CSS */
msg = "#media CSS > 767px. JS width = " + $(window).width() + " not red ! ";
$('.redthing-on-xsmall').removeClass('redthing').html(msg);
}
/* And again when window resize */
$(window).on('resize', function() {
if ($('#test-xsmall').is(':hidden')) {
msg = "#media CSS < 768px. JS width = " + $(window).width() + " red ! ";
$('.redthing-on-xsmall').addClass('redthing').html(msg);
} else {
msg = "#media CSS > 767px. JS width = " + $(window).width() + " not red ! ";
$('.redthing-on-xsmall').removeClass('redthing').html(msg);
}
});
#media (min-width: 768px) {
.hidden-xs {
display: block !important;
}
}
#media (max-width: 767px) {
.hidden-xs {
display: none !important;
}
}
.redthing-on-xsmall {
/* need a scrollbar to show window width diff between JS and css */
min-height: 1500px;
}
.redthing {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- the CSS managed Element that is tested by JS -->
<!-- class hidden-xs hides on xsmall screens (bootstrap) -->
<span id="test-xsmall" class="hidden-xs">THIS ELEMENT IS MANAGED BY CSS HIDDEN on #media lower than 767px</span>
<!-- the responsive element managed by Jquery -->
<div class="redthing-on-xsmall">THIS ELEMENT IS MANAGED BY JQUERY RED on #media max width 767px </div>
Css media query is equal to window.innerWidth. Css Media Queries calculate the scrollbar as well.
The simple and reliable way of doing this is to use Media Queries.
To demonstrate, I want to check if the screen width is greater than or equal to 992px (Bootstrap's large device):
function isLargeDevice() {
if (window.matchMedia("(min-width: 992px)").matches) {
return true;
}
return false;
}
If you are using Modernizer then it's a bit easier, here I want to check if the screen is smaller than Bootstrap's large screen (992px)
function isSmallerThanLargeScreen() {
if (Modernizr.mq('(max-width: 991px)')) {
return true;
}
return false;
}

Categories

Resources