tags:

views:

2854

answers:

4

When I'm creating new project with GWT plug in it creates a skeleton project for me. In html file there is a comment saying "Consider inlining CSS to reduce the number of requested files" Why would i consider using inline css? I tough having css in separate file not inline reduces size of my file? isn't it true?

A: 

Basically, it takes time to open up a TCP connection and request the file, so it can reduce the amount of time that it takes to load all of the files for a page.

Also, if you are going to load that file anyway, in the end it will be the same amount of bandwidth. It is better to have a reduced time for transfer than a reduced filesize.

Thomas
+1  A: 

Inline CSS has some benefits, in that it over-rules external stylesheets and always -by necessity- uses the latest CSS revisions. The down-side is that it's clearly page-specific (and so dilutes the CSS intent to separate presentation from markup), and increases the size of files over-all (since the CSS isn't cached, and it's reloaded every time and for every page -unless something's changed since I last read up about inline-css).

External stylesheets have the benefit of being cached (and so are only loaded as needed for updates or URI changes), and increase to the initial download time/file-size, but, subsequently, aren't needed to be re-loaded (unless necessary).

Also, of course, all other pages that reference the stylesheet won't download the CSS file if there's a local copy. (I don't think it matters if the pages are on one, or multiple, domains, so long as the URI is consistently referring to the same file; but I could be wrong.)

David Thomas
+1  A: 

However, most of the time this speed decrease will hardly be noticeable, and it's a good practice to separate HTML from CSS. So only do this if it is REALLY important to optimize every part of your page. Also, consider not directly inlining the CSS, but rather use some sort of object/similar that will generate the CSS inline for you. That way, you can still keep the CSS in a separate file and include it inline on the pages that need it (most won't).

PatrikAkerstrand
That's not a bad idea (the object/similar part); though I'd argue that it would be useful only on the initial entry to the site (with the intent that the initial page can render quickly, but could -in some way- load the external style sheet once the page has downloaded.
David Thomas
+13  A: 

The answer lies in the way that GWT operates. Since GWT only has one page load per module load the inlined caching doesn't really come into play.

If you just want the answer: inlined CSS reduces the number of TCP/IP connections that are needed to load all of the files that compose your project. This can be non-trivial given that you may have multiple CSS files, high latency, and other network conditions. In my line of work (state government) you aren't always guaranteed a "fat pipe".

GWT (or at least the gwt-incubator) has a mechanism for combining the optimization of inline CSS with the separation of information and layout.

Enter the ImmutableResources and StyleInjector. These two things (combined) lead to a way to load Immutable (after compile time) resources.

To use these, first download the gwt-incubator. Then add the required libraries to your module.gwt.xml

<!-- immutable resources and injecting styles -->
<inherits name="com.google.gwt.libideas.ImmutableResources" />
<inherits name="com.google.gwt.libideas.StyleInjector" />

Once that is done, create the CSS files as code resources. I keep mine in the source path like "org.project.client.resources.*". You can keep these in seperate segments such as: header.css, body.css, table.css. Go crazy, really keep things as seperate as you want. Your file path should look something like "/src/org/project/client/resources/header.css".

Now, to create the CSS interface. Now, there are some rather special things you can do with this look here. But I've just gone with the basic one.

import com.google.gwt.libideas.resources.client.CssResource;

public interface Css extends CssResource {

}

Now that you have your CssResource class (and you can have different ones) you need to create an immutable resource bundle that wraps up all of your CSS files.

import com.google.gwt.core.client.GWT;
import com.google.gwt.libideas.resources.client.ImmutableResourceBundle;

public interface ResourceBundle extends ImmutableResourceBundle {

    public static final ResourceBundle INSTANCE = GWT.create(ResourceBundle.class);

    /*
     * =============================
     * CSS
     * =============================
     */

        @Resource("org/project/client/resources/header.css")
        public Css headerCss();

        @Resource("org/project/client/resources/body.css")
        public Css bodyCss();
}

This will, at compile time, create links to the immutable CSS resources. Now we need to put (insert) those CSS resources into the module somehow. This is where the StyleInjector comes in.

I put code similar to the following into my entry point's "onModuleLoad" method.

StyleInjector.injectStylesheet(ResourceBundle.INSTANCE.headerCss().getText());
StyleInjector.injectStylesheet(ResourceBundle.INSTANCE.bodyCss().getText());

There may be other ways to accomplish the same effect in GWT but the power of the CssResource can be leveraged for more things than what I've gone over here. For example: in one of my projects I need a small change in CSS to get IE and Firefox to render what I consider to be corretly. I have two small browser specific sections in my global.css like so:

/* fix ie floating quirk */
@if user.agent ie6 ie7 ie8 {
    #someElement {
        top: -21px;
        right: 5px;
    }
}

/* fix firefox floating quirk */
@if user.agent ff gecko mozilla firefox Gecko Mozilla moz gecko1_8 {
    #someElement {
        top: -14px;
    }
}

Being able to leave this logic out of my JavaScript/Java is beautiful. There's also a small optimization here because GWT will only do the injection for the browsers that need it. (Deferred binding based on browser is how a lot of things in GWT work.)

So, the mechanism that provides inline CSS also provides other benefits while maintaining the separation of CSS.

Whats not to love?

angryundead
The method StyleInjector.injectStylesheet() is deprecated as of GWT 2.0, you can't use it consistently across all browsers...
Jon
@Jon so what is the alternative?
Epaga
Sorry, the alternative is to make sure that your CssResource is injected at runtme usnig ensureinjected() - http://google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/gwt/resources/client/CssResource.html#ensureInjected%28%29
Jon
Unfortunatly this response was written for 1.7 but I think that the ensureinjected method will yield the same results in 2.0.Thanks Jon.
angryundead