CSS Takes Effect After Page Has Rendered

CSS takes effect after page has rendered

It's not the styling; it's the jQuery UI javascript library, which is appending the necessary html to your page so that the tabs can look all pretty-like.

You have a few options. First, you can hide your tabs and display them once jQuery UI has completed its magic. Second, you can style your tabs so they look close enough to the finished output so that the change isn't so noticeable. Third, you can drop jQuery UI and style the tabs with CSS only. All valid approaches, I'd say.

Hope this helps!

EDIT:

For the first option, let's say that this is your div containing the tabs:

<div id="tabs">
...stuff...
</div>

In your stylesheet, hide #tabs:

#tabs {
display:none;
}

Then, modify your jQuery UI call like so:

var t = $("#tabs");

t.tabs({
create:function(){
t.show();
}
});

Jquery taking effect after the page is loaded

You can set your UL tag to display:none

jQuery changes elements after page has rendered

The reason why the page is finishing loading before the responsive mobile menu code runs is because your code which changes the menu is wrapped in

jQuery(function() {
//...
});

, which is equivalent to $(document).ready(), ie it tells the browser to wait until the document has finished loading before running the code.

You could try taking your responsive mobile menu scripts and instead inserting them into their own script tag inserted into the HTML immediately below the menu to which they apply, and removing the jQuery(function() {...}); wrapper. See code snippet below for a working example of what I mean:

#header-navigation { font-family: 'Lato', sans-serif; font-weight: 700; font-size: 16px; clear: both; background: #b40610; box-shadow: 0px 2px 0px #b40610;}.header-nav-menu { display: table; list-style: none; max-width: 1024px; width: 100% !important; margin: 0px auto; padding: 0px;}.header-nav-menu li {  display: table-cell; text-align: center;}.header-nav-menu li a { display: block; color: #ffffff;    text-decoration: none; white-space: nowrap; padding: 12px 0px;}.header-nav-menu li a:hover { color: #00005c; background: #e8eaf1; }
.rmm { display:block; position:relative; width:100%; padding:0px; margin:0 auto !important; line-height:19px !important;}.rmm * { -webkit-tap-highlight-color:transparent !important; text-transform: uppercase;}.rmm a { color:#ebebeb; text-decoration:none;}.rmm .rmm-main-list, .rmm .rmm-main-list li { margin:0px; padding:0px;}.rmm ul { width:auto; margin:0 auto !important; overflow:hidden; list-style:none;}

/* sublevel menu - in construction */.rmm ul li ul, .rmm ul li ul li, .rmm ul li ul li a { display:none !important; height:0px !important; width:0px !important;}/* */

.rmm .rmm-main-list li { display:inline; padding:0px; margin:0px !important;}.rmm-toggled { display:none; width:100%; position:relative; overflow:hidden; margin:0 auto !important;}.rmm-button:hover { cursor:pointer;}.rmm .rmm-toggled ul { display:none; margin:0px !important; padding:0px !important;}.rmm .rmm-toggled ul li { display:block; margin:0 auto !important;}

/* GRAPHITE STYLE */
.rmm.graphite .rmm-main-list li a { display:inline-block; padding:15px 25px; margin:0px -3px 0px -3px;}.rmm.graphite .rmm-toggled { width:95%; min-height:36px; border-radius:6px;}.rmm.graphite .rmm-toggled-controls { display:block; height:36px; color:white; text-align:left; position:relative; border-radius:6px;}.rmm.graphite .rmm-toggled-title { position:relative; top:9px; left:15px; font-size:16px; color:white; text-shadow:1px 1px 1px black;}.rmm.graphite .rmm-button { display:block; position:absolute; right:15px; top:8px;}
.rmm.graphite .rmm-button span { display:block; margin-top:4px; height:2px; background:white; width:24px;}.rmm.graphite .rmm-toggled ul li a { display:block; width:100%; text-align:center; padding:10px 0px 10px 0px; border-bottom:1px solid #ffffff;}.rmm.graphite .rmm-toggled ul li a:hover { text-decoration: underline;}.rmm.graphite .rmm-toggled ul li a:active { background-color:#444444; border-bottom:1px solid #444444; border-top:1px solid #444444;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><nav id="header-navigation">  <div class="rmm">    <ul id="menu-primary" class="header-nav-menu">      <li id="menu-item-412" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-home menu-item-412"><a href="https://www.cheekypunter.com/">Home</a></li>      <li id="menu-item-434" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-434"><a href="https://www.cheekypunter.com/about/">About</a></li>      <li id="menu-item-436" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-436"><a href="/tips/">Tips</a></li>      <li id="menu-item-433" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-433"><a href="https://www.cheekypunter.com/free-bets/">Offers</a></li>      <li id="menu-item-435" class="menu-item menu-item-type-post_type menu-item-object-page current-page-ancestor menu-item-435"><a href="https://www.cheekypunter.com/reviews/">Reviews</a></li>      <li id="menu-item-4554" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-4554"><a href="/stats/">Stats</a></li>      <li id="menu-item-893" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-893"><a href="/mobile/">Apps</a></li>      <li id="menu-item-894" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-894"><a href="/deposit/">Banking</a></li>    </ul>  </div></nav><!-- #site-navigation --><script>/*
Responsive Mobile Menu v1.0Plugin URI: responsivemobilemenu.com
Author: Sergio VitovAuthor URI: http://xmacros.com
License: CC BY 3.0 http://creativecommons.org/licenses/by/3.0/
*/
function responsiveMobileMenu() { jQuery('.rmm').each(function() {

jQuery(this).children('ul').addClass('rmm-main-list'); // mark main menu list

var $style = jQuery(this).attr('data-menu-style'); // get menu style if ( typeof $style == 'undefined' || $style == false ) { jQuery(this).addClass('graphite'); // set graphite style if style is not defined } else { jQuery(this).addClass($style); }

/* width of menu list (non-toggled) */
var $width = 0; jQuery(this).find('ul li').each(function() { $width += jQuery(this).outerWidth(); });
// if modern browser
if (jQuery.support.leadingWhitespace) { jQuery(this).css('max-width' , '1024px'); } // else { jQuery(this).css('width' , '1024px'); }
});}function getMobileMenu() {
/* build toggled dropdown menu list */
jQuery('.rmm').each(function() { var menutitle = jQuery(this).attr("data-menu-title"); if ( menutitle == "" ) { menutitle = "Menu"; } else if ( menutitle == undefined ) { menutitle = "Menu"; } var $menulist = jQuery(this).children('.rmm-main-list').html(); var $menucontrols ="<div class='rmm-toggled-controls'><div class='rmm-toggled-title'>" + menutitle + "</div><div class='rmm-button'><span> </span><span> </span><span> </span></div></div>"; jQuery(this).prepend("<div class='rmm-toggled rmm-closed'>"+$menucontrols+"<ul>"+$menulist+"</ul></div>");
});}
function adaptMenu() {
/* toggle menu on resize */
jQuery('.rmm').each(function() { var $width = jQuery(this).css('max-width'); $width = $width.replace('px', ''); if ( jQuery(this).parent().width() < 1020 ) { jQuery(this).children('.rmm-main-list').hide(0); jQuery(this).children('.rmm-toggled').show(0); } else { jQuery(this).children('.rmm-main-list').show(0); jQuery(this).children('.rmm-toggled').hide(0); } });
}
responsiveMobileMenu(); getMobileMenu(); adaptMenu();
/* slide down mobile menu on click */
jQuery('.rmm-toggled, .rmm-toggled .rmm-button').click(function(){ if ( jQuery(this).is(".rmm-closed")) { jQuery(this).find('ul').stop().show(300); jQuery(this).removeClass("rmm-closed"); } else { jQuery(this).find('ul').stop().hide(300); jQuery(this).addClass("rmm-closed"); }
});
/* hide mobile menu on resize */jQuery(window).resize(function() { adaptMenu();});</script>

When exactly is the CSS of a component loaded/applied in React?

It's hard to answer this question, because it depends on how your application is setup and built. Your results may even differ when developing and when your application is deployed.

However, there are ways to verify this yourself using your browsers developer tools.

Every major browser has developer tools with a section about "Network" traffic.
If you open your developer tools onto the "Network"-tab and then refresh your page, you'll be able to see a chronological order in which resources are fetched from the server.

You could even apply some network throttling to see the effects in action on the page.

See:

  • Chrome: https://developer.chrome.com/docs/devtools/network/#load
  • Edge: https://learn.microsoft.com/en-us/microsoft-edge/devtools-guide-chromium/network/#log-network-activity
  • Firefox: https://developer.mozilla.org/en-US/docs/Tools/Network_Monitor#opening_the_network_monitor

Log network activity

You might also be interested in reading about code-splitting as a way to change when components are loaded.

Should CSS always precede JavaScript?

This is a very interesting question. I've always put my CSS <link href="...">s before my JavaScript <script src="...">s because "I read one time that it's better." So, you're right; it's high time we do some actual research!

I set up my own test harness in Node.js (code below). Basically, I:

  • Made sure there was no HTTP caching so the browser would have to do a full download each time a page is loaded.
  • To simulate reality, I included jQuery and the H5BP CSS (so there's a decent amount of script/CSS to parse)
  • Set up two pages - one with CSS before script, one with CSS after script.
  • Recorded how long it took for the external script in the <head> to execute
  • Recorded how long it took for the inline script in the <body> to execute, which is analogous to DOMReady.
  • Delayed sending CSS and/or script to the browser by 500 ms.
  • Ran the test 20 times in the three major browsers.

Results

First, with the CSS file delayed by 500 ms (the unit is milliseconds):

     Browser: Chrome 18    | IE 9         | Firefox 9
CSS: first last | first last | first last
=======================================================
Header Exec | | |
Average | 583 36 | 559 42 | 565 49
St Dev | 15 12 | 9 7 | 13 6
------------|--------------|--------------|------------
Body Exec | | |
Average | 584 521 | 559 513 | 565 519
St Dev | 15 9 | 9 5 | 13 7

Next, I set jQuery to delay by 500 ms instead of the CSS:

     Browser: Chrome 18    | IE 9         | Firefox 9
CSS: first last | first last | first last
=======================================================
Header Exec | | |
Average | 597 556 | 562 559 | 564 564
St Dev | 14 12 | 11 7 | 8 8
------------|--------------|--------------|------------
Body Exec | | |
Average | 598 557 | 563 560 | 564 565
St Dev | 14 12 | 10 7 | 8 8

Finally, I set both jQuery and the CSS to delay by 500 ms:

     Browser: Chrome 18    | IE 9         | Firefox 9
CSS: first last | first last | first last
=======================================================
Header Exec | | |
Average | 620 560 | 577 577 | 571 567
St Dev | 16 11 | 19 9 | 9 10
------------|--------------|--------------|------------
Body Exec | | |
Average | 623 561 | 578 580 | 571 568
St Dev | 18 11 | 19 9 | 9 10

Conclusions

First, it's important to note that I'm operating under the assumption that you have scripts located in the <head> of your document (as opposed to the end of the <body>). There are various arguments regarding why you might link to your scripts in the <head> versus the end of the document, but that's outside the scope of this answer. This is strictly about whether <script>s should go before <link>s in the <head>.

In modern DESKTOP browsers, it looks like linking to CSS first never provides a performance gain. Putting CSS after script gets you a trivial amount of gain when both CSS and script are delayed, but gives you large gains when CSS is delayed. (Shown by the last columns in the first set of results.)

Given that linking to CSS last does not seem to hurt performance but can provide gains under certain circumstances, you should link to external style sheets after you link to external scripts only on desktop browsers if the performance of old browsers is not a concern. Read on for the mobile situation.

Why?

Historically, when a browser encountered a <script> tag pointing to an external resource, the browser would stop parsing the HTML, retrieve the script, execute it, then continue parsing the HTML. In contrast, if the browser encountered a <link> for an external style sheet, it would continue parsing the HTML while it fetched the CSS file (in parallel).

Hence, the widely-repeated advice to put style sheets first – they would download first, and the first script to download could be loaded in parallel.

However, modern browsers (including all of the browsers I tested with above) have implemented speculative parsing, where the browser "looks ahead" in the HTML and begins downloading resources before scripts download and execute.

In old browsers without speculative parsing, putting scripts first will affect performance since they will not download in parallel.

Browser Support

Speculative parsing was first implemented in: (along with the percentage of worldwide desktop browser users using this version or greater as of Jan 2012)

  • Chrome 1 (WebKit 525) (100%)
  • Internet Explorer 8 (75%)
  • Firefox 3.5 (96%)
  • Safari 4 (99%)
  • Opera 11.60 (85%)

In total, roughly 85% of desktop browsers in use today support speculative loading. Putting scripts before CSS will have a performance penalty on 15% of users globally; your mileage may vary based on your site's specific audience. (And remember that number is shrinking.)

On mobile browsers, it's a little harder to get definitive numbers simply due to how heterogeneous the mobile browser and OS landscape is. Since speculative rendering was implemented in WebKit 525 (released Mar 2008), and just about every worthwhile mobile browser is based on WebKit, we can conclude that "most" mobile browsers should support it. According to quirksmode, iOS 2.2/Android 1.0 use WebKit 525. I have no idea what Windows Phone looks like.

However, I ran the test on my Android 4 device, and while I saw numbers similar to the desktop results, I hooked it up to the fantastic new remote debugger in Chrome for Android, and Network tab showed that the browser was actually waiting to download the CSS until the JavaScript code completely loaded – in other words, even the newest version of WebKit for Android does not appear to support speculative parsing. I suspect it might be turned off due to the CPU, memory, and/or network constraints inherent to mobile devices.

Code

Forgive the sloppiness – this was Q&D.

File app.js

var express = require('express')
, app = express.createServer()
, fs = require('fs');

app.listen(90);

var file={};
fs.readdirSync('.').forEach(function(f) {
console.log(f)
file[f] = fs.readFileSync(f);
if (f != 'jquery.js' && f != 'style.css') app.get('/' + f, function(req,res) {
res.contentType(f);
res.send(file[f]);
});
});

app.get('/jquery.js', function(req,res) {
setTimeout(function() {
res.contentType('text/javascript');
res.send(file['jquery.js']);
}, 500);
});

app.get('/style.css', function(req,res) {
setTimeout(function() {
res.contentType('text/css');
res.send(file['style.css']);
}, 500);
});

var headresults={
css: [],
js: []
}, bodyresults={
css: [],
js: []
}
app.post('/result/:type/:time/:exec', function(req,res) {
headresults[req.params.type].push(parseInt(req.params.time, 10));
bodyresults[req.params.type].push(parseInt(req.params.exec, 10));
res.end();
});

app.get('/result/:type', function(req,res) {
var o = '';
headresults[req.params.type].forEach(function(i) {
o+='\n' + i;
});
o+='\n';
bodyresults[req.params.type].forEach(function(i) {
o+='\n' + i;
});
res.send(o);
});

File css.html

<!DOCTYPE html>
<html>
<head>
<title>CSS first</title>
<script>var start = Date.now();</script>
<link rel="stylesheet" href="style.css">
<script src="jquery.js"></script>
<script src="test.js"></script>
</head>
<body>
<script>document.write(jsload - start);bodyexec=Date.now()</script>
</body>
</html>

File js.html

<!DOCTYPE html>
<html>
<head>
<title>CSS first</title>
<script>var start = Date.now();</script>
<script src="jquery.js"></script>
<script src="test.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<script>document.write(jsload - start);bodyexec=Date.now()</script>
</body>
</html>

File test.js

var jsload = Date.now();

$(function() {
$.post('/result' + location.pathname.replace('.html','') + '/' + (jsload - start) + '/' + (bodyexec - start));
});

jQuery was jquery-1.7.1.min.js

React after render code?

componentDidMount()

This method is called once after your component is rendered. So your code would look like so.

var AppBase = React.createClass({
componentDidMount: function() {
var $this = $(ReactDOM.findDOMNode(this));
// set el height and width etc.
},

render: function () {
return (
<div className="wrapper">
<Sidebar />
<div className="inner-wrapper">
<ActionBar title="Title Here" />
<BalanceBar balance={balance} />
<div className="app-content">
<List items={items} />
</div>
</div>
</div>
);
}
});

How to call useEffect when browser is resized

This is tricky but trivial for lots of projects.
Your useEffect will be trigged one time and the function inside will be trigged everytime the user resize the browser.

Sometimes when you resize the browser you cannot access state or set the state (using useState) so i like to put the value of the width of the window outside. This way i can reuse the values anytime with almost no conflicts.

// react using hooks
import { useState, useEffect } from 'react';

// use outside the component
let isMobile = true; // variable to check width

const MyComponent = () => {

// optional: save the width of the window using state
const [width, setWidth] = useState(window.innerWidth); // check width size of the window
const handleWindowSizeChange = () => {
setWidth(window.innerWidth);
isMobile = window.innerWidth < 700 ? true : false;
};

// call your useEffect
useEffect(() => {
window.addEventListener('resize', handleWindowSizeChange);
return () => {
window.removeEventListener('resize', handleWindowSizeChange);
};
}, []);

// view of the component
return (<h1>{isMobile}</h1>)

}

Changing the CSS for a React component has effect on all other pages

If you want to localize CSS rules, then you would have to switch to modular stylesheets (works the same for sass stylesheets).

In your current structure, the component imports non-modular stylesheet and doesn't localize the changes with a unique identifier. Therfore added rules live in a global scope without a unique identifier that would localize them so that only selected components could understand them. That means that they are capable of easily overwriting the same-named rules which were previously established (import order matters here, because it would dictate how the bundler appends the output stylesheet).

So instead of holding component-related rules within ./style.scss file, rename it to ./index.module.scss and then you would utilize it within the component like so:

import React from 'react';
import styles from './index.module.scss';

const HomePage = () => {
return (
<div className={style.homepage}>
<h1 className={style.heading}>Landing page</h1>
</div>
);
};

export default HomePage;

and your stylesheet would look like:

.heading {
color: #f3f3f3;
font-family: "Cambria";
font-weight: normal;
font-size: 2rem;
}

disclaimer:

I've changed the styling convention from selecting elements by their tag, to selecting them by class, because targetting elements by tag is widely considered a bad practice [ref] , but if you want to maintain it, then you would have to provide a parent scope for such a rule (it already exists since the parent <div/> element has an assigned class.
In this case the implementation would look like:

import React from 'react';
import styles from './index.module.scss';

const HomePage = () => {
return (
<div className={style.homepage}>
<h1>Landing page</h1>
</div>
);
};

export default HomePage;

and styles:

.homepage {
h1 {
color: #f3f3f3;
font-family: "Cambria";
font-weight: normal;
font-size: 2rem;
}
}

How to make JavaScript execute after page load?

These solutions will work:

As mentioned in comments use defer:

<script src="deferMe.js" defer></script>

or

<body onload="script();">

or

document.onload = function ...

or even

window.onload = function ...

Note that the last option is a better way to go since it is unobstrusive and is considered more standard.



Related Topics



Leave a reply



Submit