Fixing CSS

August 09, 2016 in Web Development Articles

Written by Chris Minnick


CSS will have its 20th anniversary as a W3C Recommendation later this year. During those 20 years, CSS has evolved from a single, fairly simple specification into a giant (and growing) collection of modules at different levels of standardization, as well as different levels of support in different browsers. The fundamental syntax of CSS hasn’t changed in those 20 years, although we have gained more ways to select elements and the number of CSS properties has grown from the original 53 to over 250.

Managing and organizing CSS has always been an issue. The fact is, no one expected that stylesheets would get as big as they are now (I’ve seen stylesheets that are 50,000 lines long!), and no one expected that so much CSS would continue to be written by hand.

CSS Preprocessors

CSS preprocessors were created to help make writing CSS less painful and to give it some sort of semblance of being a manageable technology. The most widely used preprocessor is Sass. Sass gives us the ability to write stylesheets in a more programmatic way, and then compile them to basic CSS. However, even with preprocessors, CSS continues to be problematic due to its global nature, the preponderance of selectors that are often poorly used, and no agreed upon methodologies for how to structure or organize CSS files.

Several patterns have been proposed over the years for how to organize CSS files including OOCSS, BEM, and SMACSS. However, none of these are perfect for every project, and CSS guidelines and usage vary greatly from organization to organization and from developer to developer, even in the best case scenarios.

What nearly everyone agrees upon is that developers should impose some sort of modularity onto CSS during development. Knowing, for example, that you’ll find styles related to font sizes and styles in the _typography.scss file is far better than browsing through thousands of lines of CSS to find the right spot and then debugging to figure out why your change didn’t have the intended effect.

However, even with a perfect and well-documented system for modularizing your CSS, you still have to contend with the fact that all CSS is global and that the order of CSS rules matters. Furthermore, it’s nearly impossible to get around the fact that once all of your CSS is compiled and minified into a single file, that file is going to contain far more CSS rule sets than any one page of your site needs, as well as a ton of duplication. CSS, when used as designed, forces you to violate the DRY (don’t repeat yourself) principle and there’s nothing you can do about it. Modern browsers will cache your CSS, of course, but downloading thousands of lines of CSS to display an entry page that only requires a small fraction of those is sub-optimal.

As a randomly chosen example, the whitehouse.gov homepage loads over 160k of compressed CSS, 92% of which isn’t used on the homepage.

webpage example

CSS Libraries and Frameworks

CSS libraries and frameworks, such as the omnipresent Bootstrap, bring some order to the chaos. With a well-written and well-known library, you can manage layout and basic styling of a web app or web site and not worry that applying a certain class in one spot is going to have a different effect than if you apply it somewhere else.

That is, of course, until you decide to modify or override Bootstrap styles to fit your particular needs and site. The minute you start overriding Bootstrap styles, all of the same old CSS style management problems come back.

Is there a better way to style web applications?

Facebook proposed one particularly bold solution as part of their ReactJS library. Because of the way React renders HTML pages from a collection of independent JavaScript modules, Facebook recommended that module styling be done using JavaScript applied directly to elements, rather than through the use of CSS selectors.

As unorthodox as this solution is, it does actually make sense. If your goal is to build your application from predictable components, then encapsulating the functionality, structure, and style into those modules is the only way to be sure that they’ll always render the same way when given the same data as input. Using inline style for components is the only way to make them truly portable as well.

React uses the DOM style object to manipulate element styles, as shown in the following code:

var headerStyle = {
  fontSize: '36px',
  fontFamily: 'sans-serif',
  color: 'blue'
};

ReactDOM.render(<h1 style={headerStyle}>Welcome!</h1>, mountNode);

Can this strategy of doing all styling with JavaScript be applied outside of React?

If it can, the entire mess of CSS global scope and selector misuse can be completely eliminated — along with the need to learn, use, and maintain CSS preprocessors. With JavaScript styling, instead of having a global rule for how to style an h1 element, for example, and then overriding that later on in the stylesheet with a more specific selector, you could do something like the following:

function element (name,style,content){
  return '<'+name+' style="'+style+'">'+content+'</'+name+'>';
}

var headerH1Style = 'color:red;font-size:24px;';
var headerDivStyle = 'width:100%; text-align:center;';
var pageHeader = element('div',headerDivStyle,
                 element('h1',headerH1Style,'Welcome!'));

Of course, this is an extremely simplistic example. But, if you flesh this out and work on creating a system of building style and HTML using JavaScript, you’ll end up with a dumbed-down version of React.

JavaScript and CSS

From a styling perspective, the benefits of building and styling web UIs using only JavaScript is that it gives you control over your CSS scope and you get all the benefits of a CSS preprocessor. Plus, JavaScript-styled web content is completely dynamic whereas Sass variables, function, and mixins get compiled to static CSS.

One possible objection to this approach to style is that today’s browsers are highly optimized for compiling, rendering, and drawing CSS. Using JavaScript to render styles may not be as efficient as using a stylesheet.

Another objection is that JavaScript styling requires knowledge of JavaScript. Since JavaScript is usually prerequisite for having a job as a front-end developer, this argument seems less important to me than the potential performance issue.

To long-time web developers, who were indoctrinated with the basic rules that style, content, and functionality should be kept strictly separate, styling with JavaScript is heresy. We were taught that the proper way to apply styles is through taking advantage of CSS cascading and selectors. Applying styles directly to elements using JavaScript violates this principle.

For now, the approach that I prefer is to use a known framework, such as Bootstrap, for global layout and styling. Inside of components that are meant to be reusable, however, I lean heavily towards using inline styles for local CSS.

Author: Chris Minnick, one of Accelebrate’s instructors.

Accelebrate offers private training in JavaScript, CSS, and React.js.


Written by Chris Minnick

Chris Minnick

Chris has authored and co-authored over a dozen books including titles in the For Dummies series, as well as several books teaching kids to code. Chris specializes in JavaScript technologies and writes and maintains courseware that’s used for training software developers at some of the largest companies in the world.
  


Learn faster

Our live, instructor-led lectures are far more effective than pre-recorded classes

Satisfaction guarantee

If your team is not 100% satisfied with your training, we do what's necessary to make it right

Learn online from anywhere

Whether you are at home or in the office, we make learning interactive and engaging

Multiple Payment Options

We accept check, ACH/EFT, major credit cards, and most purchase orders



Recent Training Locations

Alabama

Birmingham

Huntsville

Montgomery

Alaska

Anchorage

Arizona

Phoenix

Tucson

Arkansas

Fayetteville

Little Rock

California

Los Angeles

Oakland

Orange County

Sacramento

San Diego

San Francisco

San Jose

Colorado

Boulder

Colorado Springs

Denver

Connecticut

Hartford

DC

Washington

Florida

Fort Lauderdale

Jacksonville

Miami

Orlando

Tampa

Georgia

Atlanta

Augusta

Savannah

Hawaii

Honolulu

Idaho

Boise

Illinois

Chicago

Indiana

Indianapolis

Iowa

Cedar Rapids

Des Moines

Kansas

Wichita

Kentucky

Lexington

Louisville

Louisiana

New Orleans

Maine

Portland

Maryland

Annapolis

Baltimore

Frederick

Hagerstown

Massachusetts

Boston

Cambridge

Springfield

Michigan

Ann Arbor

Detroit

Grand Rapids

Minnesota

Minneapolis

Saint Paul

Mississippi

Jackson

Missouri

Kansas City

St. Louis

Nebraska

Lincoln

Omaha

Nevada

Las Vegas

Reno

New Jersey

Princeton

New Mexico

Albuquerque

New York

Albany

Buffalo

New York City

White Plains

North Carolina

Charlotte

Durham

Raleigh

Ohio

Akron

Canton

Cincinnati

Cleveland

Columbus

Dayton

Oklahoma

Oklahoma City

Tulsa

Oregon

Portland

Pennsylvania

Philadelphia

Pittsburgh

Rhode Island

Providence

South Carolina

Charleston

Columbia

Greenville

Tennessee

Knoxville

Memphis

Nashville

Texas

Austin

Dallas

El Paso

Houston

San Antonio

Utah

Salt Lake City

Virginia

Alexandria

Arlington

Norfolk

Richmond

Washington

Seattle

Tacoma

West Virginia

Charleston

Wisconsin

Madison

Milwaukee

Alberta

Calgary

Edmonton

British Columbia

Vancouver

Manitoba

Winnipeg

Nova Scotia

Halifax

Ontario

Ottawa

Toronto

Quebec

Montreal

Puerto Rico

San Juan