One of my favorite quotes pertaining to development is very close to one of my favorite quotes pertaining to design:
“The code you write makes you a programmer. The code you delete makes you a good one. The code you don’t have to write makes you a great one.” – Mario Fusco
“A designer knows they have achieved perfection not when there is nothing left to add, but when there is nothing left to take away.” – Antoine de Saint-Exupery
Both advocate for a “less-is-more” philosophy, and are good reminders that behind the sleek designs of iconic interfaces from Apple, Uber, and Google are highly optimized technology stacks designed to quickly get the right information to the right people. Here are a few areas to consider when striving to achieve a sleeker UX:
Text-to-Code Ratio
When a search engine crawls a page for content, it has to sort through way more information than meets the eye. This includes all the structure, styles, behavior, and visuals that are assembled by your browser, resulting in a beautifully orchestrated web experience. The catch-22 here is that some of the prettier, more impressive effects that can be utilized by a site to captivate audiences usually require a lot more code to pull off. That impacts one of the little talked about factors of page performance called “text-to-code ratio”. This metric is the measurement of how much human-readable content exists within a block of code.
While it does not directly influence page ranking in search engines, it is considered a key indicator for opportunities where page performance can be improved. Google recommends a text-to-code ratio between 20% and 70% per page. While on the surface this may seem like an easy goal to achieve, taking a closer look at your tech stack might reveal an abundance of needless complexity and that your pages could be performing better with the right kind of adjustments. This is where designers and developers need to work together to figure out if these effects make sense when keeping your key stakeholder’s objectives in mind.
How Styles Impact Performance
While in-line styles may save time to implement in some cases, they’re also one of the biggest offenders when your text-to-code ratio begins to fall. As developers, we’ve probably all done it at some point in our career, and in some cases it’s unavoidable. Whether included between style tags or as rules inserted into an element’s style attribute, it’s important to minimize these instances as much as possible.
In this practical example, I will show you how to improve your ratio by over 10% with very little effort.
Before:
<h2 style="font-size:21px">Numbered Things</h2> <ul style="margin-top:10px;padding-left:10px"> <li style="font-size:14px">Thing 1</li> <li style="font-size:14px">Thing 2</li> <li style="font-size:14px">Thing 3</li> <li style="font-size:14px">Thing 4</li> </ul> <h2 style="font-size:21px">Lettered Things</h2> <ul style="margin-top:10px;padding-left:10px"> <li style="font-size:14px">Thing A</li> <li style="font-size:14px">Thing B</li> <li style="font-size:14px">Thing C</li> <li style="font-size:14px">Thing D</li> </ul>
If we take some time to work with a designer to come up with reusable styles that can be automatically applied by utilizing a reusable and cache-friendly stylesheet, we can begin to see some improvements.
After:
<link rel="stylesheet" href="/css/styles.css" /> <h2 class="heading">Numbered Things</h2> <ul class="things"> <li>Thing 1</li> <li>Thing 2</li> <li>Thing 3</li> <li>Thing 4</li> </ul> <h2 class="heading">Lettered Things</h2> <ul class="things"> <li>Thing A</li> <li>Thing B</li> <li>Thing C</li> <li>Thing D</li> </ul>
In our CSS file we have the following rules:
.heading { font-size: 21px; } .things { margin-top: 10px; padding-left: 10px; font-size: 14px; }
Before | After |
Raw Length: 521 Characters Text-Only Length: 95 Characters Final Ratio: 18.23% Content |
Raw Length: 318 Characters Text-Only Length: 95 Characters Final Ratio: 29.87% Content |
Our first example fell short of the 20% recommended minimum text-to-code ratio. However, making just a few adjustments to how we apply these styles resulted in an improved ratio by more than 11%. While Google won’t favor one over the other, it’s pretty clear to see that the second example is a lot cleaner, more organized, and because fewer characters are involved, will arrive to a user’s browser faster.
Another reason this becomes important is for those agencies who use utility-based pricing for hosting sites, where every byte transmitted by the host translates to an expense. While these are only small examples to illustrate the idea, you can probably begin to see the impact at a larger scale.
How Scripts Affect Performance
JavaScript. Love it or hate it, it’s deserving of respect. Without JavaScript, the web would not be the same. We would be bombarded with page refreshes, bandwidth issues, and general usability limitations. At Grafik, we standardized on jQuery for its backwards compatibility and polyfills for older browsers, namely IE11.
Our agency utilizes a design pattern called “atomic design,” which essentially turns page features into smaller individual apps that are integrated together on the back end. These visual components allow a content author to construct pages from scratch without touching a single line of code. This helps provide control over the design without detracting from the overall approved site design.
Sometimes, these atomic components introduce configuration-controlled interactions driven by auto-generated scripts. Where this begins to become problematic is when the same component is used multiple times on the same page, or even in conjunction with other components, adding needless bloat to the document itself.
Let’s take another look at a practical example which approximates an atomic component, much like what we would use on a production site. This might include using a button that does something cool when the viewer interacts with it, placed on page a couple times.
Before:
<div id="component-0" class="component cool-text"> <p>Check it out, I’m the 1st component on the page!</p> <button type="button">Click Me!</button> <script> ( function( $ ) { $( function() { $( '#component-0 button' ).on( 'click', function() { $( this ).html( 'Yay, I was clicked!' ); } ); } ); } )( jQuery ); </script> </div> <div id="component-1" class="component cool-text"> <p>Hey, I’m the 2nd component on the page.</p> <button type="button">Click Me!</button> <script> ( function( $ ) { $( function() { $( '#component-1 button' ).on( 'click', function() { $( this ).html( 'Yay, I was clicked!' ); } ); } ); } )( jQuery ); </script> </div>
Even though the content of these components is unique per-use, it’s pretty easy to see that an almost identical copy of the script is created to control each instance of the atomic component. Let’s make some adjustments that allow us to run a single script that can do the work of both, without sacrificing functionality.
After:
<div id="component-0" class="component cool-text"> <p>Check it out, I’m the 1st component on the page!</p> <button type="button">Click Me!</button> <script type="application/json">{ message: "Yay, I was Clicked!" }</script> </div> <div id="component-1" class="component cool-text"> <p>Hey, I’m the 2nd component on the page.</p> <button type="button">Click Me!</button> <script type="application/json">{ message: "Hooray, I'm Clicked!" }</script> </div> ... <script src="/js/scripts.js"></script>
Instead of writing JavaScript dynamically, we structure our scripts to instead output JSON payloads which only contain the bits of information that previously made each script unique per use.
( function( $ ) { $( function() { $( '.component.cool-text' ).each( function( i ) { var Component = $( this ); var Config = JSON.parse( Component.find( 'script' ).html() ); Component.find( 'button' ).on( 'click', function() { $( this ).html( Config.message ); } ); } ); } ); } )( jQuery );
The migrated script we place into /js/scripts.js then becomes the unified brain of the operation, serving all the functionality without needing to be dynamically generated. Only the HTML necessary to include the script is counted against the ratio, not the entire contents of the file.
Before | After |
Raw Length: 644 Characters Text-Only Length: 108 Characters Final Ratio: 16.77% Content |
Raw Length: 492 Characters Text-Only Length: 108 Characters Final Ratio: 21.95% Content |
Again, our first example fell well short of the recommended minimum density, but the improvements we made brought us within range to nearly 22%. The effects of this approach can vary widely since the nature of JavaScript is very different from application to application. In our example, we have a button that changes its own text when clicked, which by comparison to a real-world application is fairly simple. More intricate features will net a greater benefit since more code is typically involved under that scenario.
Key Takeaways
Pages are only as good as the content they contain, and I don’t think that will change any time soon. What will affect your ranking is how many people leave your site prematurely due to being frustrated or because they’ve had to sift through too much bloat and not enough substance. Paying attention to your text-to-code ratio can be one of many ways to achieve higher performance benchmarks on your pages.
It’s also critical to set yourself up for success from the beginning. One of the best ways to achieve this is by having designers and developers working and collaborating together more closely so that design challenges are solved with the greatest level of attention possible. Take a look at your text-to-html ratio, your styles, and your scripts.
Hopefully you’ve got some great ideas on how to improve your page performance after reading these strategies. If you’re interested in seeing some of these concepts in action, please check out our Technology offerings to see how we can bring your vision to life, or you can look through our Case Studies which are all fine examples of how we’ve helped others actualize their visions.