Is it possible to conditionally include CSS? - asp.net

I have an ascx that has some CSS in it. It is possible that this ascx could be added multiple times to a page. The CSS that it uses would only need to be included once.
Is it possible to conditionally include CSS? If so how?
Is this considered bad practice?

I have an ascx that has some CSS in it... Is this considered bad practice?
Yes. Your CSS rules should ideally be defined in a separate, static css file that gets loaded only once in the header by your master page. CSS in the body is not standards compliant.
If you set up good caching rules on your static CSS files, this will significantly reduce the amount of data you pull across the wire because the CSS rules won't need to be loaded again for each page load. If you want to only include this file in the header if certain dependent ASCX files get rendered, look at Neil Fenwick's answer.
Update
For whatever reason, Neil Fenwick seems to have deleted his answer. Hopefully he won't mind my reproducing it here:
Definitely YES, it is possible.
I would recommend looking at a library like ClientDependency to manage your CSS and JS includes & dependencies.
Good examples for how to include given on ClientDependency codeplex page.
Its good practice to organise your CSS and JS dependencies so that you can assert their requirement multiple times, but only emit the dependency in the output once.

The ClientScriptManager can handle this simply by checking whether or not some particular "script" has been added. Intended for javascript, but works for anything.
if(!Page.ClientScript.IsStartupScriptRegistered("mykey")) {
Page.ClientScript.RegisterStartupScript(this.GetType(), "mykey", "<link type=\"text/css\" href=\"stylesheet.css\"/>", false);
}

You might be very interested in looking into Modernizr which allows you to do plenty of interesting test and load different resources (for example CSS) depending on test result. For example you might want to load rounded-images.css if the browser does not support border-radius etc.

Building on Neil's answer. We make use of Telerik's ASP MVC extensions to manage our JavaScript and CSS in ASP.NET MVC. It allows for "smart" inclusion of JS and CSS (even from a partial-view) preventing file duplication. It comes with other bells-and-whistles as well (like file merging and compression).
This is probably not applicable to your exact situation based on your post (raw ASP.NET), but thought I would mention it for the sake of ASP.NET MVC users looking for the same thing.

Put that in the head of the html.
<pre>
<!--[if gte IE 8]>
<link rel="stylesheet" type="text/css" href="ie8-and-up.css" /> <![endif]-->
</pre>
For more info go to: http://css-tricks.com/132-how-to-create-an-ie-only-stylesheet/
GTE means greater than.
Horrible practice. Unless that is all you do at your work since that is going to create a big workload since each css file might need to be changed in the future.

Related

"Eliminate render-blocking CSS in above-the-fold content"

I've been using Google PageSpeed insights to try and improve my site's performance, and so far it's proven extremely successful. Things like deferring scripts worked beautifully, since I already had an in-house version of jQuery's .ready() to defer scripts until the page had loaded fully, all I had to do was inline that particular function and move the full scripts to the end of the page. That worked great.
But now I find myself glaring at the one remaining yellow dot on the checklist: "Eliminate render-blocking CSS in above-the-fold content".
The way my CSS is set up is to have one global _.css file containing styles that apply to the page structure in general, or are used in more than one or two places across the site. Most pages then have an associated CSS file (for instance, party.php has party.css) containing styles specific to that particular page. All CSS files are cached indefinitely, as I append /t=FILEMTIME to filenames (and later remove them with .htaccess) in order to guarantee that files are updated when they are changed.
So anyway, Google recommends inlining critical styles needed for above-the-fold content. Trouble is... well, take a look at this screenshot: http://prntscr.com/1qt49e
As you can see... ALL of the content is above-the-fold! People hate scrolling, especially on a game that involves loading many pages. So I designed the site to fit on one screen (assuming a good enough resolution). So that means... ALL of the styles apply to above-the-fold content! So... is there any solution? Or am I stuck with that yellow mark on an otherwise near-perfect score?
A related question has been asked before: What is “above-the-fold content” in Google Pagespeed?
Firstly you have to notice that this is all about 'mobile pages'.
So when I interpreted your question and screenshot correctly, then this is not for your site!
On the contrary - doing some of the things advised by Google in their guidelines will things make worse than better for 'normal' websites.
And not everything that comes from Google is the "holy grail" just because it comes from Google. And they themselves are not a good role model if you have a look at their HTML markup.
The best advice I could give you is:
Set width and height on replaced elements in your CSS, so that the browser can layout the elements and doesn't have to wait for the replaced content!
Additionally why do you use different CSS files, rather than just one?
The additional request is worse than the small amount of data volume. And after the first request the CSS file is cached anyway.
The things one should always take care of are:
reduce the number of requests as much as possible
keep your overall page weight as low as possible
And don't puzzle your brain about how to get 100% of Google's PageSpeed Insights tool ...! ;-)
Addition 1: Here is the page on which Google shows us, what they recommend for Optimize CSS Delivery.
As said before, I don't think that this is neither realistic nor that it makes sense for a "normal" website! Because mainly when you have a responsive web design it is most certain that you use media queries and other layout styles. So if you are not gonna load your CSS first and in a blocking manner you'll get a FOUT (Flash Of Unstyled Text). I really do not believe that this is "better" than at least some more milliseconds to render the page!
Imho Google is starting a new "hype" (when I have a look at all the question about it here on Stackoverflow) ...!
How I got a 99/100 on Google Page Speed (for mobile)
TLDR: Compress and embed your entire css script between your <style></style> tags.
I've been chasing down that elusive 100/100 score for about a week now. Like you, the last remaining item was was eliminating "render-blocking css for above the fold content."
Surely there is an easy solve?? Nope. I tried out Filament group's loadCSS solution. Too much .js for my liking.
What about async attributes for css (like js)? They don't exist.
I was ready to give up. Then it dawned on me. If linking the script was blocking the render, what if I instead embedded my entire css in the head instead. That way there was nothing to block.
It seemed absolutely WRONG to embed 1263 lines of CSS in my style tag. But I gave it a whirl. I compressed it (and prefixed it) first using:
postcss -u autoprefixer --autoprefixer.browsers 'last 2 versions' -u cssnano --cssnano.autoprefixer false *.css -d min/ See the NPM postcss package.
Now it was just one LONG line of space-less css. I plopped the css in <style>your;great-wall-of-china-long;css;here</style> tags on my home page. Then I re-analyzed with page speed insights.
I went from 90/100 to 99/100 on mobile!!!
This goes against everything in me (and probably you). But it SOLVED the problem. I'm just using it on my home page for now and including the compressed css programmatically via a PHP include.
YMMV (your mileage may vary) pending on the length of your css. Google may ding you for too much above the fold content. But don't assume; test!
Notes
I'm only doing this on my home page for now so people get a FAST render on my most important page.
Your css won't get cached. I'm not too worried though. The second they hit another page on my site, the .css will get cached (see Note 1).
Few tips that may help:
I came across this article in CSS optimization yesterday:
CSS profiling for ... optimization
A lot of useful info on CSS and what CSS causes the most performance drains.
I saw the following presentation on jQueryUK on "hidden secrets" in Googe Chrome (Canary) Dev Tools:
DevTools Can do that.
Check out the sections on Time to First Paint, repaints and costly CSS.
Also, if you are using a loader like requireJS you could have a look at one of the CSS loader plugins, called require-CSS, which uses CSSO - a optimzer that also does structural optimization, eg. merging blocks with identical properties. I used it a few times and it can save quite a lot of CSS from case to case.
Off the question:
I second #Enzino in creating a sprite for all the small icons you are loading. The file sizes are so small it does not really warrant a server roundtrip for each icon. Also keep in mind the total number of concurrent http requests are browser can do. So requests for a larger number of small icons are "render-blocking" as well. Although an empty page compare to yours, I like how duckduckgo loads for example.
Please have a look on the following page https://varvy.com/pagespeed/render-blocking-css.html .
This helped me to get rid of "Render Blocking CSS". I used the following code in order to remove "Render Blocking CSS". Now in google page speed insight I am not getting issue related with render blocking css.
<!-- loadCSS -->
<script src="https://cdn.rawgit.com/filamentgroup/loadCSS/6b637fe0/src/cssrelpreload.js"></script>
<script src="https://cdn.rawgit.com/filamentgroup/loadCSS/6b637fe0/src/loadCSS.js"></script>
<script src="https://cdn.rawgit.com/filamentgroup/loadCSS/6b637fe0/src/onloadCSS.js"></script>
<script>
/*!
loadCSS: load a CSS file asynchronously.
*/
function loadCSS(href){
var ss = window.document.createElement('link'),
ref = window.document.getElementsByTagName('head')[0];
ss.rel = 'stylesheet';
ss.href = href;
// temporarily, set media to something non-matching to ensure it'll
// fetch without blocking render
ss.media = 'only x';
ref.parentNode.insertBefore(ss, ref);
setTimeout( function(){
// set media back to `all` so that the stylesheet applies once it loads
ss.media = 'all';
},0);
}
loadCSS('styles.css');
</script>
<noscript>
<!-- Let's not assume anything -->
<link rel="stylesheet" href="styles.css">
</noscript>
I too have struggled with this new pagespeed metric.
Although I have found no practical way to get my score back up to %100 there are a few things I have found helpful.
Combining all css into one file helped a lot. All my sites are back up to %95 - %98.
The only other thing I could think of was to inline all the necessary css (which appears to be most of it - at least for my pages) on the first page to get the sweet high score. Although it may help your speed score this will probably make your page load slower though.
The 2019 optimal solution for this is HTTP/2 Server Push.
You do not need any hacky javascript solutions or inline styles. However, you do need a server that supports HTTP 2.0 (any modern server version will), which itself requires your server to run SSL. However, with Let's Encrypt there's no reason not to be using SSL anyway.
My site https://r.je/ has a 100/100 score for both mobile and desktop.
The reason for these errors is that the browser gets the HTML, then has to wait for the CSS to be downloaded before the page can be rendered. Using HTTP2 you can send both the HTML and the CSS at the same time.
You can use HTTP/2 push by setting the Link header.
Apache example (.htaccess):
Header add Link "</style.css>; as=style; rel=preload, </font.css>; as=style; rel=preload"
For NGINX you can add the header to your location tag in the server configuration:
location = / {
add_header Link "</style.css>; as=style; rel=preload, </font.css>; as=style; rel=preload";
}
With this header set, the browser receives the HTML and CSS at the same time which stops the CSS from blocking rendering.
You will want to tweak it so that the CSS is only sent on the first request, but the Link header is the most complete and least hacky solution to "Eliminate Render Blocking Javascript and CSS"
For a detailed discussion, take a look at my post here: Eliminate Render Blocking CSS using HTTP/2 Push
Consider using a package to automatically generate inline styles from your css files. A good one is Grunt Critical or Critical css for Laravel.

Generating dynamic CSS

What is the best way to handle style that that is user-customized? Just as an example of the result I'm looking for, this would suffice:
body {
color: {{ user.profile.text_color }};
}
However, serving CSS as a view seems like it would cause a significant amount of overhead in a file that is constantly requested, so this is probably not a good solution.
The user does not have access to the CSS files and we must assume that they have no web development knowledge.
However, serving CSS as a view seems like it would cause a significant amount of overhead in a file that is constantly requested, so this is probably not a good solution.
And what if you would generate that CSS once?
Default CSS is: /common/css.css
Member customize CSS, now <link /> elements points to /user-specific/123.css?ts=123123123. 123 is of course an identifier of the member, and ts parameter contains a timestamp - a date of last CSS modification
Make sure that your CSS generator sets proper HTTP headers responsible for client-side caching
User browser request a CSS file - server replies with simple 304 Not Modified header - there is no need for any script execution or contents download
When member modifies his CSS then you just update ts - once again just a single request is needed
Do the CSS dynamically via a view as normal, but use aggressive caching so that it loads quickly.
You can try django mediagenerato, actually I read this Q and I was searching for solution like you, then I found that Django-mediagenerator
I didn't tried it yet but it seams to be a solution.

Insert dependencies dynamically in View (Javascript and CSS Files)

Friends, I am willing to follow the rules of the W3C where it is recommended that javascript and CSS files should be in individual files and not within the page.
Good, following this rule, and not wanting to overload the master page, I would like to embed the dependencies dynamically. So how could I insert the libraries dynamically? I think the bigger problem is the Ajax requests.
Example:
<script type="text/javascript" src="http://sstatic.net/so/js/master.js?v=6523"></script>
I tried using the JavascriptResult, but he writes the content on the page, and do not run as "Stream."
Any help is welcome. Thanks
If I understand correctly the problem, you want to add script files dynamically to the page.
You can try jQuery load function, that can parse for you the result in very intuitive way.

Move generated javascript out of rendered html

One SEO advice we got was to move all javascript to external files, so the code could be removed from the text. For fixed scripts this is not a problem, but some scripts need to be generated as they depend on some ClientId that is generated by asp.net.
Can I use the ScriptManager (from asp.net Ajax or from Telerik) to send this script to the browser or do I need to write my own component for that?
I found only ways to combine fixed files and/or embedded resources (also fixed).
How about registering the ClientIDs in an inline Javascript array/hash, and have your external JS file iterate through that?
Spiderbots do not read JavaScript blocks. This advice is plain wrong.
Some javascript can break W3C validators (and possibly cause issues with some spiderbots)
You can reduce this by placing this code around your javascript:
< !-- no script
... your javascript code and functions ...
// -->
Note: remove the space between "<" and "!" as it seems to comment out the example here :-)

Preferred method for linking to stylesheets from a UserControl?

We primarily use an ASP.NET environment at work. Right now I'm building an application which uses "Modules", which is just a UserControl, with its' Javascript right in the control, and a link element to the stylesheet for that control. I want to keep it modular, and would like the style of this control to be independent from the markup/javascript.
So I'm wondering what the preferred method of doing this is? Obviously if I didn't want the "theme" functionality I'm after, I could just use style tags at the top of the control. Right now I have a link element, as I said, and this isn't proper I don't think.
Does anyone have any preferred methods, and if so, what and why?
I considered ASP.NET themes briefly, but the idea of these controls are a little different, I think.
It's basically a shopping cart system. I don't want to get into it all, but we are using a really neat security system, and we don't want to use a premade shopping cart. I'm developing a set of controls that can be dropped on a page, for instance in SiteFinity (which is the CMS system we use) or for any other project we might have. Normally I would compile these into a DLL so we get ACTUAL controls we can drag & drop from the toolbox, then I could use internal "generic" styling and allow for any additive styling someone might want, as well as supplying a few fancier styles as well.
This is the first time I've ever done this, or really the first time anyone in our shop has done this either so I'm kind of figuring it out as I go. I might be pretty far off-base, but hopefully I'm not.
Right, the idea for this is to have a "theme", which is really just a CSS file and a jQuery template. I have them named the same, and have a Theme property on the usercontrol to set it.
When these controls are finalized, I might refactor the javascript to a RegisterScriptBlock on the code-behind, but for now they just in script tags on the control itself.
What prompted this question was DebugBar for IE, giving me warnings that link elements are not allowed inside a div. I don't much care, but after thinking about it, I had no idea how to link to the css file without doing that. I considered very briefly having an 'empty' link tag on the master and then setting THAT in the code behind on Page_Load of the UserControl, but that just seems like ass.
I could use #import I guess but I think link tags are preferred, correct?
It sounds like you're rolling your own theme engine... why not use ASP.NET Themes?
If you're determined to do it yourself, here's some code from the CssFriendly project that may be of interest to you. (I think it should be ok to post the code as long as I cite where it's from.) The .css files are flagged as Embedded Resource and the code below is used to include them as needed.
string filePath = page.ClientScript.GetWebResourceUrl(type, css);
// if filePath is not empty, embedded CSS exists -- register it
if (!String.IsNullOrEmpty(filePath))
{
if (!Helpers.HeadContainsLinkHref(page, filePath))
{
HtmlLink link = new HtmlLink();
link.Href = page.ResolveUrl(filePath);
link.Attributes["type"] = "text/css";
link.Attributes["rel"] = "stylesheet";
page.Header.Controls.Add(link);
}
}
I think what you're supposed to do is use Page.RegisterScriptBlock to register your script blocks. Best-case you shouldn't have them inline in your ascx inside script blocks. This isn't always possible, but theoretically it's the best way.
Ideally your styles should be separate from your markup as well. Your controls can have classes and IDs, but your style is based on your application and not your controls. Controls can theoretically be used in other applications where you might want a different style.
It depends on how big your app is, and whether or not it's dependent on Themes elsewhere, IMHO.
If you're using a .skin file, or if the majority of the app is also plugged into the theme, you might as well go with the theme.
But if it's just a few styles you need, you're better off to set the stylesheet manually, keep your css file external (inline styles are a PITA and defeat one of the core purposes of css).
In either case, don't forget to set the CssClass attribute on your controls.
To be proper I would have an import.css file - structure the naming of the classes to follow your controls, and import the styles within the header of the document.
If you have a module called "30DayPricingCalc" then you could name the classes/id's:
30DayPricingCalc.css
.30daypricingcalc_main_content
{
...
}
Also if you haven't I would setup a list of generic reusable styles to save you room. Since elements will allow multiple classes per object.
Also, link tags matter a lot less now than they used to. we're well past support for IE5 generation browsers and IE6 supports the #import tag.
Cheers!

Resources