CSS Selector Specificity

To determine which CSS style in your style sheet will outrank the others you need to calculate the “Specificity” for each of the styles based on the selectors used to target the HTML element. To calculate use the following rules:

HTML Tag Selector: 1 point ( i.e. p, div, span )
CSS Class Selector: 10 points ( i.e. class=”redText” )
HTML ID Selector: 100 points ( i.e. id=”HeaderBox” )

Example Styles:

span { color:yellow; } => has a score of 1 = 1
#HeaderBox span {color:blue;} => has a score of 100+1 = 101
#HeaderBox .redText span { color:red; } => has a score of 100+10+1 = 111

Example HTML:

This text will be blue.

This text will be red.

This text will be yellow.

Pseudo-Pseudo Classes

If you need a common chunk of text added before content you can use Pseudo selectors to accomplish this. An example is adding a chunk of text to the front of all blockquote elements in your HTML defining the quote as belonging to a specific category.

blockquote:before { content: "Classical"; }

Or you can use pseudo selectors to add check marks to the front of all links which have been visited by the user.

a:visited { padding: 20px; background: transparent url(/images/check.png) no-repeat top left;

Here are some others you might find useful:

a:before { content:"click here"; }
a:after { content:"click here"; }
p:first-letter { font-size:20px; }

These only work in newer more advanced browsers ( down with IE6 )

a[title] { color:red; } this is how you select a tag using one of its attributes as a qualifier. In other words this selector will only apply the color red to links that have a title.

a[title=special] { color:green; } this one applies the color green to all links which have a title and that title equals “special”.

ASP.net: User Control Specific CSS/JS Loading

(Update: the BaseUserControl class has been updated to handle loading specific CSS or JS files or one or the other. This allows a common CSS or JS file to be passed for a set of controls making up a module within your application.)

(Update: The BaseUserControl class has been updated to handle instances where your UserControl is loaded multiple times on the same page. This will stop the CSS and JS from being loaded multiple times for each control.)

(Update: If your pages are using MasterPages for their designs make sure you add a runat=”server” to the head tag of your master pages. If you do not the Header property of the page will be null. )

In ASP.net we run into an issue when it comes our User Controls and their corresponding CSS loading in the main CSS files even when that User Control is not included in the 90% of the pages a user calls. (this is the same with JavaScript files)

In order to make sure that my User Control’s CSS is not unnecessarily loaded in the application’s main CSS file and to maintain a little more order in my design I like to use a little programming magic. This magic allows me to only load the CSS for a User Control when it is included in a page or another User Control.

To accomplish this magic I create a Base User Control from which all my User Controls inherit. This base control contains a method called LoadResources which does the following:

  1. Pulls the name of the Current Control making the call.
  2. Adds a Link tag with the path to the CSS file for the current control
  3. Adds a Script tag with the path to the JavaScript file for the current control

(All of the above are based on the CSS and JavaScript files having the same name as the control and those files being located in the same location as the current control.)

Code:

public class BaseUserControl : UserControl

{

    #region Private Fields

    private string _controlName;

    #endregion

    #region Protected Methods

    /// 

    /// Used if the control has custom CSS or Javascript

    /// which needs to be loaded with the control.

    /// The resources consist of a .css and .js files 

    /// which have the same name as the control. This method

    /// will search the control's location for those 2

    /// files and add them as CSS and Javascript links to

    /// the control's ascx content.

    /// 

    protected void LoadResources()

    {

        PullControlName();

        LoadCssFile();

        LoadJsFile();

    }

    /// 

    /// Loads the resources.

    /// 

    /// Name of the file.

    /// Type of the file.

    protected void LoadResources(string fileName, FileType fileType)

    {

        switch (fileType)

        {

            case FileType.Script:

                LoadJsFile(fileName);

                break;

            case FileType.Style:

                LoadCssFile(fileName);

                break;

        }

    }

    /// 

    /// Loads the resources.

    /// 

    /// 
styleFileName">
Name of the style file.

    /// 
scriptFileName">
Name of the script file.

    protected void LoadResources(string styleFileName, string scriptFileName)

    {

        LoadCssFile(styleFileName);

        LoadJsFile(scriptFileName);

    }

    #endregion

    #region Private Methods

    private void PullControlName()

    {

        string controlType = GetType().ToString();

        List<string> controlParts = controlType.Split('_').ToList();

        if (controlParts.Count > 0)

        {

            if (!string.IsNullOrEmpty(controlParts[controlParts.Count - 2]))

            {

                _controlName = controlParts[controlParts.Count - 2];

            }

        }

    }

    private void LoadCssFile()

    {

        try

        {

            // Injects the CSS for this control into the page header

            string cssUrl = ResolveUrl(_controlName + ".css");

            string cssPath = cssUrl.Remove(0, 1).Replace('/', '\\');

            if (File.Exists(Request.PhysicalApplicationPath + cssPath))

            {

                string controlId = _controlName + "Style";

                if (!DoesControlExist(controlId))

                {

                    HtmlLink css = new HtmlLink();

                    css.ID = controlId;

                    css.Href = cssUrl;

                    css.Attributes.Add("rel", "stylesheet");

                    css.Attributes.Add("type", "text/css");

                    Page.Header.Controls.Add(css);

                }

            }

        }

        catch (Exception ex)

        {

            //TODO: Handle exception as a warning

        }

    }

    private void LoadCssFile(string fileName)

    {

        try

        {

            // Injects the CSS for this control into the page header

            string cssUrl = ResolveUrl(fileName);

            string cssPath = cssUrl.Remove(0, 1).Replace('/', '\\');

            if (File.Exists(Request.PhysicalApplicationPath + cssPath))

            {

                string controlId = fileName + "Style";

                if (!DoesControlExist(controlId))

                {

                    HtmlLink css = new HtmlLink();

                    css.ID = controlId;

                    css.Href = cssUrl;

                    css.Attributes.Add("rel", "stylesheet");

                    css.Attributes.Add("type", "text/css");

                    Page.Header.Controls.Add(css);

                }

            }

        }

        catch (Exception ex)

        {

            //TODO: Handle exception as a warning

        }

    }

    private void LoadJsFile()

    {

        try

        {

            // Injects the JavaScript for this control into the page header

            string jsUrl = ResolveUrl(_controlName + ".js");

            string jsPath = jsUrl.Remove(0, 1).Replace('/', '\\');

            if (File.Exists(Request.PhysicalApplicationPath + jsPath))

            {

                string controlId = _controlName + "Script";

                if (!DoesControlExist(controlId))

                {

                    HtmlGenericControl js = new HtmlGenericControl("script");

                    js.ID = controlId;

                    js.Attributes.Add("type", "text/javascript");

                    js.Attributes.Add("src", jsUrl);

                    Page.Header.Controls.Add(js);

                }

            }

        }

        catch (Exception ex)

        {

            //TODO: Handle exception as a warning

        }

    }

    private void LoadJsFile(string fileName)

    {

        try

        {

            // Injects the JavaScript for this control into the page header

            string jsUrl = ResolveUrl(fileName);

            string jsPath = jsUrl.Remove(0, 1).Replace('/', '\\');

            if (File.Exists(Request.PhysicalApplicationPath + jsPath))

            {

                string controlId = fileName + "Script";

                if (!DoesControlExist(controlId))

                {

                    HtmlGenericControl js = new HtmlGenericControl("script");

                    js.ID = controlId;

                    js.Attributes.Add("type", "text/javascript");

                    js.Attributes.Add("src", jsUrl);

                    Page.Header.Controls.Add(js);

                }

            }

        }

        catch (Exception ex)

        {

            //TODO: Handle exception as a warning

        }

    }

    private bool DoesControlExist(string controlId)

    {

        object control = Page.Header.FindControl(controlId);

        if (control != null)

            return true;

        return false;

    }

    #endregion

    #region Utility Classes

    /// 

    /// Types of files which are accepted by the 

    /// resource loader.

    /// 

    public enum FileType

    {

        /// 

        /// Cascading Style Sheet files

        /// 

        Style,

        /// 

        /// JavaScript files

        /// 

        Script

    }

    #endregion

}

CSS: Using EM for Font Sizes

Based on the default font size of the browser the ’em’ is used simply as a multiplier. For example lets say the default font size is 16px (the most common browser default size) and you wanted the H1 tag to be twice that size you would simply set the font-size of the H1 tag to 2em which would effectively set the height of the text to 32px. 

A good practice which allows you to more reliably set text size in your design is to first set the default browser text size to something which you can easily multiply by. If the common default browser text size is 16px we could scale it down to 10px which is extremely easy to multiply by. We can do this bey setting the default font-size to 62.5%. After doing this we can then use multipliers of 10 to get our text to the sizes we want. So now if we wanted our H1 tag to be 15px we could simply set the font-size to 1.5em. 

Why mess with em values. Because we are no longer hard coding our text to exact pixel sizes. Instead all of our text is now relative to the browser’s current default font-size which we can then alter to grow or shrink all of the text on our page.

CSS: Override Inline Styles from Stylesheet

Normally inline styles within your html markup is a way to override more global stayles which you have set within your stylesheets. Well if you have been developing within 3rd party CMS systems or 3rd party controls for any length of time you must have run into a situation where styles exists which you cannot alter because they are wrapped up in the 3rd party markup. In cases like this there is a very useful CSS option we have which allows us to do the exact opposite, we can actually set styles in our stylesheets which will override the more specific inline styles. 

This is done by adding some extra info to our CSS selectors. We simply add the [style] psuedo selector to our CSS class within the stylesheet. See the example below.


This inline style now gives us a blue rectangle with red text. Which is extremely hard to read.

With the use of the psuedo selector we can now override the inline style with this.

div[style] {
background-color: yellow !important; color: green !important;
}

CSS: Hide Link Text, Let Your Images Shine Through

In systems like DotNetNuke and other such CMS systems you are sometimes stuck with auto-generated links containing auto-generated text. In most cases when you are trying to make a graphically rich UI with beautiful buttons this auto-generated crap becomes a real pain. In order to let your beautiful button graphics shine through just hide the text link tag using CSS.

Setting the Width and Height to 100% and the Display to block  allows the link to expand and fill its containing element, this is useful for links on logo images making the entire image clickable. Setting the Font-Size to 0px; makes the text completely disappear from the screen but is still there.

#logo a {
width:100%; height:100%;
text-decoration:none;

display:block;
font-size:0px;}

CSS Sprites, No Flash Rollovers, Reduced Bandwidth

To reduce the unsightly flashes that happen when 2 images are used for control (button) states (hover, press) in a HTML page just put the images together in one file and use CSS to move the background image to the appropriate state location within the image. This method has been labeled CSS Sprites by web developers and is extremely effective for removing the flash. But what is even more important is it speeds up your site in several ways.

Code Example:

Sprite Image
Sprite Image

div#noflash {width:200px; height:30px; background:transparent url(../Images/BlackWhiteSprite.jpg) no-repeat top left; }

div#noflash:hover {background:transparent url(../Images/BlackWhiteSprite.jpg) no-repeat -200px 0px;}

The code above shows a white square that is 200px wide and 30px high by default. Once it is hovered over by a user’s mouse instead of loading a completely different image for the hover state we simply take the same image, already in cache, and we just move it to the right -200px to reveal the black portion of the image. That is all there is to it, you can move a background side to side, top to bottom and a mixture of both to get to any x/y location within the image.

You may think that many smaller files reduce your visitor’s wait for a page to load, but you are mistaken. Your individual image sizes may be really small but part of your image’s size is meta-data describing the image (size, type, etc.). This meta data adds bulk to every image you create. To test this for yourself you can take a folder full of images and examine its properties in windows by right clicking it. When the properties window opens record the size of the folders contents. Then take all those images and in your favorite image editor and combine them all into one large image by tiling them. Now examine the new image’s properties and you will find that the combined image’s size is 80-90% smaller than the folder containing all the individual images. This is because there is only one set of meta data for the one combination image, instead of a set for each individual image.

Of course this does not mean you should take all the images in your site and create one monolithic sprite image, that could end up being massive and would really slow down the loading of your pages. What it does mean is that you should take related images, such as button states, icons, etc. and create sets out of them. Then combine the related images in each set creating a single sprite image for each of the sets. This allows one image to be loaded by the browser, cached and then used for n+ images.

How else does this method improve your site’s performance? Glad you asked! It reduces the # of Http requests that have to be made by a client’s browser to get the content needed to display a page. Why does this matter? Each Http request is a round trip from the client’s computer to the server on which the web site lives. Each resource (css, javascript, html, Images, etc.) that makes up the web page requires an individual request. The more requests that are required to build the page the longer it takes.

Lets say that a request from your browser to this server takes an average of 39ms and there are 35 images used in this web page. Now excluding the variable lag created by different sized images which can affect the response time the total response time base off the average for all of those images to reach your browser is 1365ms. Now lets say that those 35 images could be combined into 6 related sets the response time is now 234ms almost 6 times shorter.

Now of course your image is bigger now that you combined them, but remember that the overall size by combining has been reduced. Smaller size less time. So not only did we reduce the overall sice of all the images that have to be sent across the internet but we also reduced the number of requests that have to be made. Your page just loaded faster! Your visitors are thanking you! Your traffic just increased! Your bandwidth useage just went down! Your hosting bill just decreased! All I see here are benefits…