├── .gitignore
├── LICENSE-GPL
├── LICENSE-MIT
├── README.md
├── dist
├── eCSSential.js
└── eCSSential.min.js
├── examples
├── concat
│ ├── css
│ │ ├── all.css
│ │ ├── combined
│ │ │ ├── all.min-20em.css
│ │ │ ├── all.min-20em.min-37.5em.css
│ │ │ ├── all.min-20em.min-37.5em.min-50em.css
│ │ │ ├── all.min-20em.min-37.5em.min-50em.min-62.5em.css
│ │ │ ├── min-20em.min-37.5em.min-50em.min-62.5em.css
│ │ │ ├── min-37.5em.min-50em.min-62.5em.css
│ │ │ ├── min-50em.min-62.5em.css
│ │ │ └── min-62.5em.css
│ │ ├── min-20em.css
│ │ ├── min-37.5em.css
│ │ ├── min-50em.css
│ │ └── min-62.5em.css
│ └── index.html
├── default
│ ├── css
│ │ ├── all.css
│ │ ├── min-20em.css
│ │ ├── min-37.5em.css
│ │ ├── min-50em.css
│ │ └── min-62.5em.css
│ └── index.html
├── logdata.js
├── oldIE-separate-CSS
│ ├── css
│ │ ├── all.css
│ │ ├── min-20em.css
│ │ ├── min-20em.min-37.5em.min-50em.min-62.5em.css
│ │ ├── min-37.5em.css
│ │ ├── min-50em.css
│ │ └── min-62.5em.css
│ └── index.html
└── oldIE
│ ├── css
│ ├── all.css
│ ├── min-20em.css
│ ├── min-37.5em.css
│ ├── min-50em.css
│ └── min-62.5em.css
│ ├── index.html
│ └── respond.min.js
├── grunt.js
├── libs
├── matchMedia
│ └── matchMedia.js
└── qunit
│ ├── qunit.css
│ └── qunit.js
├── package.json
├── src
└── eCSSential.js
└── test
└── unit
├── eCSSential.html
└── eCSSential_test.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
--------------------------------------------------------------------------------
/LICENSE-GPL:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
--------------------------------------------------------------------------------
/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012 Scott Jehl
2 |
3 | Permission is hereby granted, free of charge, to any person
4 | obtaining a copy of this software and associated documentation
5 | files (the "Software"), to deal in the Software without
6 | restriction, including without limitation the rights to use,
7 | copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the
9 | Software is furnished to do so, subject to the following
10 | conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # No Longer Maintained
2 | Thanks for checking out this project. We're keeping it here for historical purposes but otherwise, it's no longer maintained and we do not recommend using it now that standards for CSS loading have evolved.
3 |
4 | # eCSSential
5 | ## Making responsive CSS load the way it should.
6 |
7 | - [c]2012 @scottjehl, Filament Group, Inc.
8 | - Licenses: MIT, GPLv2
9 |
10 | ### The Problem
11 |
12 | Loading CSS in an optimized or prioritized fashion is very difficult. In order for a website to load cleanly, all CSS needed for rendering that page layout must be referenced in the `head` of a document. This is because stylesheets loaded in this way will block page rendering until they are loaded and ready to apply. If a stylesheet is referenced later in a document, or loaded dynamically via JS, users will often see a FOUC while that stylesheet loads concurrently with page rendering.
13 |
14 | Unfortunately, this limitation can make for a lot of overhead in responsive designs, particularly if a stylesheet contains a large amount of CSS for breakpoints that don't currently apply at a particular viewport size, or worse, CSS that won't ever apply on a particular device. More unfortunate, using separate `link` elements with `media` attributes to reference stylesheets with their intended breakpoints [doesn't prevent those stylesheets from downloading and blocking page rendering](http://scottjehl.github.com/CSS-Download-Tests/), even in environments where they don't currently or will never apply.
15 |
16 | Lastly, if for some reason a stylesheet takes a long time to load, most browsers will let it continue to block page rendering for 30 seconds or more!
17 |
18 |
19 | ### How eCSSential Helps
20 |
21 | eCSSential is a JavaScript utility that is designed to make browsers download files in a faster, more responsible manner than they do by default. Technically speaking, it is a tiny bit of JavaScript that when placed in the `head` of a page, determines which of your stylesheets should be loaded immediately and block page rendering (any stylesheets intended for mobile-first breakpoints that currently apply), which stylesheets should be deferred to load asynchronously (any stylesheets intended for breakpoints that don't currently apply to the current viewport size, but could apply later, given the device's screen size), and which stylesheets should never be loaded at all (any stylesheets intended for viewport dimensions that are larger than the device's screen). Once sorted, the essential (or eCSSential if you will) files are loaded in a way that ensures page rendering will be blocked until they're ready. The other less-essential files are loaded in a non-blocking way, letting the page render while they are fetched.
22 |
23 | In one further improvement to browsers' default loading behavior, stylesheets that are loaded in a blocking manner are given 8 seconds (by default) to load before they are refetched asynchonously, allowing the page to appear and be used.
24 |
25 |
26 | ## Check out the demos
27 |
28 | - [Default eCSSential Usage](http://scottjehl.github.com/eCSSential/examples/default)
29 | - [eCSSential with concatenated CSS files](http://scottjehl.github.com/eCSSential/examples/concat)
30 | - [eCSSential with IE-specific stylesheets](http://scottjehl.github.com/eCSSential/examples/oldIE-separate-CSS)
31 | - [eCSSential with a media query polyfill](http://scottjehl.github.com/eCSSential/examples/oldIE)
32 |
33 | ### Seeing the Results
34 |
35 | If you're in a desktop browser, you can pop open the demo page (try the [concatentated files demo](http://scottjehl.github.com/eCSSential/examples/concat) for the best performance) and check your developer console to see which stylesheets were loaded immediately and which were deferred; changing your viewport/window width and reloading the page will change where this loading split occurs.
36 |
37 |
38 | ## How To Use eCSSential
39 |
40 | Using eCSSential is as easy as including the full source of eCSSential.min.js (find that in the `/dist` folder) inline in the head of your page, and then calling `eCSSential()`, passing each of the paths to your CSS files paired with a media query describing where they are intended to apply.
41 |
42 |
43 | ...
44 |
55 |
56 |
57 | From this, eCSSential will be able to sort which are important up-front, and which can be deferred, or never loaded at all, and inject `link` elements to load the files accordingly.
58 |
59 | Because eCSSential requires JavaScript support to perform its optimizations, you might want to follow it with a `noscript` element containing references to any stylesheets you would prefer to load in non-JavaScript environments. If you don't do this, non-JavaScript users will simply receive an unstyled page, so it's up to you how you provide a fallback.
60 |
61 |
62 | ...
63 |
70 |
71 |
76 |
77 |
78 | That's it! With eCSSential in place, your pages will now render much faster on many devices (particularly small screens).
79 |
80 |
81 | ## Setting configuration options
82 |
83 | eCSSential comes with a number of defaults that can be overridden on a per-call basis. These options are configured by passing a second argument to the `eCSSential` function in the form of an object with one or more key/value pairs.
84 |
85 | eCSSential( {
86 | "all": "css/all.css",
87 | "(min-width: 20em)": "css/min-20em.css",
88 | [_...more files..._]
89 | },
90 | // SET CONFIGURATION OPTIONS HERE
91 | { optionA: true, optionB: 500 } );
92 |
93 | The following sections will reference configuration options that are defined in this manner.
94 |
95 |
96 | ## Optimizing Further with File Concatenation
97 |
98 | By default, eCSSential creates individual `link` elements for each stylesheet it requests, which, depending on the number of CSS files you have, can make for a lot of HTTP requests. Reducing HTTP requests is one of the best ways to improve the performance of a site, so eCSSential is designed to work with concatenated files if you instruct it to do so.
99 |
100 | Optionally, eCSSential can be configured to fetch all of your CSS via only 2 HTTP requests, of which the first request is immediate and blocking (synchronous), and the second is deferred and non-blocking (asynchronous). To use this feature, you'll need the help of a server-side concatenation tool, such as [QuickConcat](https://github.com/filamentgroup/quickconcat), or a build system that generates all static versions of your potential CSS file combinations. The `examples` directory contains a demo of this feature. You can also find it [here](http://scottjehl.github.com/eCSSential/examples/concat). The demo uses static generated combinations of the CSS files.
101 |
102 | To configure eCSSential to fetch concatenated files via a single request, you'll need to define a configuration property of `concat` as a function. The only rules for that `concat` function is that it should accept an array and return a string. For example, if your concatenated CSS files have filenames that are a long joined name of the files they contain, separated by periods with their directories and extensions removed, you might define a `concat` option like this:
103 |
104 | eCSSential({
105 | "all": "css/all.css",
106 | "(min-width: 20em)": "css/min-20em.css",
107 | [_...more files..._]
108 | },
109 | {
110 | concat: function( files ){
111 | return "combined/" + arr.join("").replace( /css\/?/gmi, "" ) + "css";
112 | }
113 | });
114 |
115 | With that in place, a concatenated URL would end up somethign like this: `css/all.css.min-20em.css.min-37em.css`.
116 |
117 | To use with a dynamic concatenator like [QuickConcat](https://github.com/filamentgroup/quickconcat), your concat function might prepend comma-joined CSS files with a `quickconcat.php?files=` path...
118 |
119 | eCSSential({
120 | "all": "all.css",
121 | "(min-width: 20em)": "min-20em.css",
122 | [_...more files..._]
123 | },
124 | {
125 | concat: function( files ){
126 | return "quickconcat.php?files=" + files.join();
127 | }
128 | });
129 |
130 | Because it's free-form, the `concat` option can work with any concatenation tool you'd like. Check out the `examples/concat/index.html` file for a working example of the `concat` option.
131 |
132 |
133 | ## Supporting Older Versions of IE
134 |
135 | Internet Explorer versions 6-8 have no CSS3 Media Query support. Because of this, you'll need to do a little extra work to get a mobile-first responsive design to render with a proper layout in these browsers.
136 |
137 | Generally, you can do that one of two ways:
138 |
139 | - create a separate stylesheet to conditionally deliver layout fixes to these browsers
140 | - use a media query polyfill like [Respond.js](https://github.com/scottjehl/Respond) to make the media queries work like they do in other browsers.
141 |
142 | Regardless of your preferred approach, eCSSential has you covered.
143 |
144 | ### Delivering IE-specific stylesheets
145 |
146 | To deliver stylesheets ONLY to specific versions of Internet Explorer, you can reference stylesheets using `IE6`, `IE7`, or `IE8` in place of a media query. You can use one or many of these too, depending on which versions you'd like a stylesheet to load. In the following example, the last stylesheet referenced load in IE 6-8:
147 |
148 | eCSSential({
149 | "all": "all.css",
150 | "(min-width: 20em)": "css/min-20em.css",
151 | "(min-width: 37.5em)": "css/min-37.5em.css",
152 | "(min-width: 50em)": "css/min-50em.css",
153 | "(min-width: 62.5em)": "css/min-62.5em.css",
154 | "IE6 IE7 IE8": "css/iedesktopfixes.css"
155 | });
156 |
157 | ### Delivering all stylesheets to IE with intent to polyfill media query support
158 |
159 | Alternatively, if you would like to load all of your stylesheets in IE 6-8 polyfill media query support to make them work, you can simply pass the configuration `oldIE` option, via the same mechanism used to define a `concat` option above.
160 |
161 | eCSSential({
162 | "all": "all.css",
163 | "(min-width: 20em)": "css/min-20em.css",
164 | "(min-width: 37.5em)": "css/min-37.5em.css",
165 | "(min-width: 50em)": "css/min-50em.css",
166 | "(min-width: 62.5em)": "css/min-62.5em.css"
167 | }, { oldIE: true } );
168 |
169 | When doing this, just be sure to add [Respond.js](https://github.com/scottjehl/Respond) or an equivalent workaround after the references to these CSS files.
170 |
171 |
172 | ## Changing the maximum time rendering will block
173 |
174 | By default, eCSSential will allow a blocking stylesheet to load for 8 seconds before refetching it and showing the page in whatever state it may be. If you'd like to change this timeout, just pass a different millisecond-based `patience` value in the configuration object, like so:
175 |
176 | eCSSential({
177 | "all": "all.css",
178 | "(min-width: 20em)": "css/min-20em.css",
179 | "(min-width: 37.5em)": "css/min-37.5em.css",
180 | "(min-width: 50em)": "css/min-50em.css",
181 | "(min-width: 62.5em)": "css/min-62.5em.css"
182 | //set the max rendering timeout to 6 seconds instead of 8
183 | }, { patience: 6000 } );
184 |
185 |
186 | ## Disabling the default deferred stylesheet qualifier
187 |
188 | By default, eCSSential will not load stylesheets that are targeted at dimensions not possible on a particular device (based on its screen size). This ammounts to better performance on small screens by reducing HTTP requests, but it does have the potential drawback that if the browser window is moved to a different sized screen, it may not have all of the styles it needs optimize for that new screen. This is somewhat of an edge case, but if you'd like to make sure every non-applicable CSS file is loaded asynchonously, you can pass the `deferAll` option as true.
189 |
190 | eCSSential({
191 | "all": "all.css",
192 | "(min-width: 20em)": "css/min-20em.css",
193 | "(min-width: 37.5em)": "css/min-37.5em.css",
194 | "(min-width: 50em)": "css/min-50em.css",
195 | "(min-width: 62.5em)": "css/min-62.5em.css"
196 | }, { deferAll: true } );
197 |
198 |
199 | ## Further notes
200 |
201 | - eCSSential includes the `window.matchMedia` polyfill so that it can run CSS3 media queries via JavaScript in browsers that don't support matchMedia. If you don't need to include the `window.matchMedia` polyfill (if say, perhaps it's already in your page), just remove the reference to it in the `grunt.js` file and generate a new build.
202 |
203 |
204 | ## FAQ
205 |
206 | ### Are There Drawbacks to using eCSSential?
207 |
208 | It will make your responsive websites load a lot faster on mobile devices. Oh wait, did you say drawbacks?
209 |
210 |
211 |
212 |
--------------------------------------------------------------------------------
/dist/eCSSential.js:
--------------------------------------------------------------------------------
1 | /*! eCSSential - v0.1.0 - 2012-06-08
2 | * https://github.com/scottjehl/eCSSential
3 | * Copyright (c) 2012 Scott Jehl, @scottjehl, Filament Group, Inc.; Licensed GPL, MIT; Includes matchMedia.js: http://j.mp/jay3wJ (MIT) */
4 |
5 | /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */
6 |
7 | window.matchMedia = window.matchMedia || (function(doc, undefined){
8 |
9 | var bool,
10 | docElem = doc.documentElement,
11 | refNode = docElem.firstElementChild || docElem.firstChild,
12 | // fakeBody required for
13 | fakeBody = doc.createElement('body'),
14 | div = doc.createElement('div');
15 |
16 | div.id = 'mq-test-1';
17 | div.style.cssText = "position:absolute;top:-100em";
18 | fakeBody.style.background = "none";
19 | fakeBody.appendChild(div);
20 |
21 | return function(q){
22 |
23 | div.innerHTML = '';
24 |
25 | docElem.insertBefore(fakeBody, refNode);
26 | bool = div.offsetWidth === 42;
27 | docElem.removeChild(fakeBody);
28 |
29 | return { matches: bool, media: q };
30 | };
31 |
32 | }(document));
33 | /*! eCSSential
34 | * https://github.com/scottjehl/eCSSential
35 | * Copyright (c) 2012 Scott Jehl, @scottjehl, Filament Group, Inc.; Licensed GPL, MIT; Includes matchMedia.js: http://j.mp/jay3wJ (MIT) */
36 |
37 | window.eCSSential = function( css, config ){
38 | "use strict";
39 | var load = [],
40 | defer = [],
41 | timedout = [],
42 | // All options false or null by default; no need for a mixin
43 | o = config || {},
44 | w = window,
45 | d = w.document,
46 | insLoc = d.getElementsByTagName( "script" )[0],
47 | whre = /(min|max)-(width|height)/gmi,
48 | ieV = w.navigator.appVersion.match( /MSIE ([678])\./ ) && RegExp.$1,
49 | ieRe = new RegExp( "(IE" + ieV + ")|(IE)", "g" );
50 |
51 | for( var mq in css ){
52 | if( css.hasOwnProperty( mq ) ){
53 | // if media query evaluates true,
54 | // or if the browser is IE 6-8 and the key is a IEx match, or the o.oldIE option is true,
55 | // queue the stylesheet for a renderer-blocking load
56 | var iekey = mq.match( ieRe );
57 |
58 | if( w.matchMedia( mq ).matches || ( ieV && ( o.oldIE || iekey && iekey[ 1 ] ) ) ){
59 | load.push( {
60 | //keep the media attribute, but leave it as "all" if it was an "IEx" key
61 | mq: o.oldIE || iekey ? "all" : mq,
62 | href: css[ mq ]
63 | } );
64 | }
65 | // otherwise, queue for deferred load some stylesheets that didn't evaluate true the first time
66 | // Note: this means many stylesheets intended for conditions that could never apply (such as a width wider than the maximum device width) will be loaded anyway, causing more HTTP requests.
67 | // min/max-width/height queries are by default evaluated to see if they could never apply on the current screen
68 | // by running them as a "device" query instead of a viewport query.
69 | // You can disable this behavior and defer every stylesheet by setting the deferAll configuration option
70 | else if( !iekey && ( o.deferAll || !mq.match( whre ) || w.matchMedia( mq.replace( whre, "$1-device-$2" ) ).matches ) ){
71 | defer.push( { mq: mq, href: css[ mq ] } );
72 | }
73 | }
74 | }
75 |
76 | // Make link elements (or one concat'd link) from an array of Stylesheets
77 | // first argument is array of urls, second argument is bool for inserting meta element marker (only used in block)
78 | function makeLinks( arr ){
79 | var marker = arr === load ? '' : '',
80 | start = '',
82 | hrefs = [],
83 | hrefmqs = [];
84 |
85 | for( var i in arr ){
86 | if( arr.hasOwnProperty( i ) ){
87 | hrefs.push( arr[ i ].href );
88 | hrefmqs.push( arr[ i ].href + '" media="' + arr[ i ].mq );
89 | }
90 | }
91 |
92 | // if the concat option is specified (recommended), pass the array through it and dump the resulting string into a single stylesheet url
93 | if( o.concat ){
94 | return start + o.concat( hrefs ) + end + marker;
95 | }
96 | // otherwise, make separate link elements
97 | else {
98 | return start + hrefmqs.join( '" ' + end + start ) + end + marker;
99 | }
100 | }
101 |
102 | // document.write the stylesheets that should block
103 | if( load.length ){
104 | d.write( makeLinks( load ) );
105 | insLoc = d.getElementById( "eCSS" );
106 |
107 | // set up timeout to stop a stylesheet from blocking after 8 seconds
108 | // or by however many ms are passed via o.patience
109 | var links = insLoc.parentNode.getElementsByTagName( "link" );
110 | for(var i = 0, il = links.length; i< il; i++ ){
111 | (function( c ){
112 | var t = w.setTimeout(function(){
113 | var next = c.nextSibling;
114 | c.parentNode.removeChild( c );
115 | next.parentNode.insertBefore( c, next );
116 | timedout.push( c );
117 | }, o.patience || 8000 );
118 | c.onload = function(){
119 | clearTimeout( t );
120 | };
121 | }( links[ i ] ));
122 | }
123 | }
124 |
125 | // defer the load of the stylesheet that could later apply
126 | if( defer.length ){
127 | var div = d.createElement( "div" );
128 | div.innerHTML = makeLinks( defer );
129 | insLoc.parentNode.insertBefore( div, insLoc );
130 | }
131 | // return data for testing
132 | return { css: css, config: config, block: load, defer: defer, timedout: timedout };
133 | };
134 |
--------------------------------------------------------------------------------
/dist/eCSSential.min.js:
--------------------------------------------------------------------------------
1 | /*! eCSSential - v0.1.0 - 2012-06-08
2 | * https://github.com/scottjehl/eCSSential
3 | * Copyright (c) 2012 Scott Jehl, @scottjehl, Filament Group, Inc.; Licensed GPL, MIT; Includes matchMedia.js: http://j.mp/jay3wJ (MIT) */
4 | window.matchMedia=window.matchMedia||function(a,b){var c,d=a.documentElement,e=d.firstElementChild||d.firstChild,f=a.createElement("body"),g=a.createElement("div");return g.id="mq-test-1",g.style.cssText="position:absolute;top:-100em",f.style.background="none",f.appendChild(g),function(a){return g.innerHTML='',d.insertBefore(f,e),c=g.offsetWidth===42,d.removeChild(f),{matches:c,media:a}}}(document),window.eCSSential=function(a,b){function o(a){var b=a===c?'':"",d='',g=[],h=[];for(var i in a)a.hasOwnProperty(i)&&(g.push(a[i].href),h.push(a[i].href+'" media="'+a[i].mq));return f.concat?d+f.concat(g)+e+b:d+h.join('" '+e+d)+e+b}"use strict";var c=[],d=[],e=[],f=b||{},g=window,h=g.document,i=h.getElementsByTagName("script")[0],j=/(min|max)-(width|height)/gmi,k=g.navigator.appVersion.match(/MSIE ([678])\./)&&RegExp.$1,l=new RegExp("(IE"+k+")|(IE)","g");for(var m in a)if(a.hasOwnProperty(m)){var n=m.match(l);g.matchMedia(m).matches||k&&(f.oldIE||n&&n[1])?c.push({mq:f.oldIE||n?"all":m,href:a[m]}):!n&&(f.deferAll||!m.match(j)||g.matchMedia(m.replace(j,"$1-device-$2")).matches)&&d.push({mq:m,href:a[m]})}if(c.length){h.write(o(c)),i=h.getElementById("eCSS");var p=i.parentNode.getElementsByTagName("link");for(var q=0,r=p.length;q
2 |
3 |
4 |
5 |
6 | eCSSential | Test Template
7 |
8 |
23 |
24 |
25 |
26 |
27 |
28 |
eCSSential
29 |
An experiment in optimized loading of mobile-first responsive CSS.
30 |
[c]2012 @scottjehl, Filament Group, Inc. MIT/GPLv2
31 |
32 |
Page load data
33 |
34 | JavaScript wasn't available so the fallback stylesheet loaded.
35 |
36 |
37 |
38 |
39 |
40 |
CSS output
41 |
In browsers that support CSS pseudo elements (like :after{}), each loaded stylesheet will add a line of text below to announce its presence and whether its intended breakpoint is currently active. Note that this script is merely concerned with improving stylesheet loading performance, but how and where those loaded stylesheets apply is still controlled by CSS media queries.
An experiment in optimized loading of mobile-first responsive CSS.
29 |
[c]2012 @scottjehl, Filament Group, Inc. MIT/GPLv2
30 |
31 |
32 |
Page load data
33 |
34 | JavaScript wasn't available so the fallback stylesheet loaded.
35 |
36 |
37 |
38 |
39 |
40 |
CSS output
41 |
In browsers that support CSS pseudo elements (like :after{}), each loaded stylesheet will add a line of text below to announce its presence and whether its intended breakpoint is currently active. Note that this script is merely concerned with improving stylesheet loading performance, but how and where those loaded stylesheets apply is still controlled by CSS media queries.
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/examples/logdata.js:
--------------------------------------------------------------------------------
1 | /* this file is for logging data in the example pages. Nothing fancy here; look away. */
2 | (function(){
3 | var data = document.getElementById( "data" );
4 | if( data && loadCSS ){
5 | var info = [],
6 | loaded = [];
7 |
8 | // available css info
9 | info.push( "
Available StyleSheets
" );
10 | if( loadCSS.css ){
11 | for( var i in loadCSS.css ){
12 | if( loadCSS.css.hasOwnProperty( i ) ){
13 | info.push( "
An experiment in optimized loading of mobile-first responsive CSS.
32 |
[c]2012 @scottjehl, Filament Group, Inc. MIT/GPLv2
33 |
34 |
Page load data
35 |
36 | JavaScript wasn't available so the fallback stylesheet loaded.
37 |
38 |
39 |
40 |
41 |
42 |
CSS output
43 |
In browsers that support CSS pseudo elements (like :after{}), each loaded stylesheet will add a line of text below to announce its presence and whether its intended breakpoint is currently active. Note that this script is merely concerned with improving stylesheet loading performance, but how and where those loaded stylesheets apply is still controlled by CSS media queries.
An experiment in optimized loading of mobile-first responsive CSS.
36 |
[c]2012 @scottjehl, Filament Group, Inc. MIT/GPLv2
37 |
38 |
Page load data
39 |
40 | JavaScript wasn't available so the fallback stylesheet loaded.
41 |
42 |
43 |
44 |
45 |
46 |
CSS output
47 |
In browsers that support CSS pseudo elements (like :after{}), each loaded stylesheet will add a line of text below to announce its presence and whether its intended breakpoint is currently active. Note that this script is merely concerned with improving stylesheet loading performance, but how and where those loaded stylesheets apply is still controlled by CSS media queries.