<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Compatibility - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Compatibility - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 23 Jun 2026 22:45:20 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/compatibility/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ What is Cross-Browser Compatibility? How to Build Websites that Work Everywhere ]]>
                </title>
                <description>
                    <![CDATA[ When building for the web, it's easy to develop tunnel vision and only build for yourself. You may overlook the diverse needs of your audience and focus solely on your preferences and how things look on your preferred browser. This can cause you to m... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-cross-browser-compatibility/</link>
                <guid isPermaLink="false">66c5a34fdd1f1e4092a3256c</guid>
                
                    <category>
                        <![CDATA[ Browsers ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Compatibility ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ophy Boamah ]]>
                </dc:creator>
                <pubDate>Wed, 06 Mar 2024 18:26:43 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/03/Cross-Browser.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When building for the web, it's easy to develop tunnel vision and only build for yourself. You may overlook the diverse needs of your audience and focus solely on your preferences and how things look on your preferred browser. This can cause you to miss out on crucial functionality aspects and lead to future compatibility issues on other browsers. </p>
<p>In this article, we'll dive into practical strategies for achieving cross-browser compatibility, focusing on specific UI components like form elements, scrollbars, and fonts. Then we'll discuss some general best practices that every web developer should adopt.</p>
<blockquote>
<p>“Remember that you are not your users — just because your site works on your MacBook Pro or high-end Galaxy Nexus, doesn't mean it will work for all your users!” – <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Introduction">MDN Web Docs</a></p>
</blockquote>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-cross-browser-compatibility">What is Cross-Browser Compatibility?</a></li>
<li><a class="post-section-overview" href="#heading-common-cross-browser-issues-and-solutions">Common Cross-Browser Issues and Solutions</a></li>
<li><a class="post-section-overview" href="#heading-best-practices-for-cross-browser-compatibility">Best Practices for Cross-Browser Compatibility</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ul>
<h2 id="heading-what-is-cross-browser-compatibility">What is Cross-Browser Compatibility?</h2>
<p>In simple terms, cross-browser compatibility is about ensuring that your website delivers a consistent, top-notch experience for all users, regardless of their browser choice. </p>
<p>Browsers use different engines, so by default they render websites differently. In order to get your websites to look and work the same regardless of the user's browser requires an understanding of unique browser capabilities.</p>
<p>Cross-browser compatibility says that ideally, a website should look and function the same whether someone is viewing it on Chrome, Microsoft Edge and Opera (powered by Blink engine), Firefox (powered by Gecko engine) or even Safari (powered by WebKit engine). </p>
<h3 id="heading-benefits-of-cross-browser-compatibility">Benefits of Cross-Browser Compatibility:</h3>
<ol>
<li>Wider reach – your websites are accessible to more users, regardless of the browser they use.</li>
<li>Consistent User Experience – your websites have a uniform look and functionality across platforms.</li>
<li>Better Search Engine Optimization (SEO) – your websites get higher rankings from being more user-friendly.</li>
</ol>
<h2 id="heading-common-cross-browser-issues-and-solutions">Common Cross-Browser Issues and Solutions</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/browserstack.png" alt="Image" width="600" height="400" loading="lazy">
<em>Infographic showing test results of a web page on different browsers. Image credit Browserstack</em></p>
<h3 id="heading-form-elements">Form Elements</h3>
<p>The appearance and behavior of form elements like <code>&lt;input&gt;</code>, <code>&lt;select&gt;</code>, <code>&lt;textarea&gt;</code>, and <code>&lt;button&gt;</code> can vary significantly across browsers. This affects both the visual aspect and usability of forms, including how users interact with them (for example, clicking, focusing, and typing).</p>
<p>For instance, placeholder text in <code>&lt;input&gt;</code> fields may appear fainter in one browser and more pronounced in another, leading to readability issues. </p>
<p>To resolve this:</p>
<ul>
<li>Use CSS to standardize the appearance of form elements as much as possible.</li>
<li>For placeholders, ensure contrast and legibility across browsers:</li>
</ul>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">::placeholder</span> { <span class="hljs-comment">/* Chrome, Firefox, Opera, Safari 10.1+ */</span>
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#909090</span>;
  <span class="hljs-attribute">opacity</span>: <span class="hljs-number">1</span>; <span class="hljs-comment">/* Firefox */</span>
}

<span class="hljs-selector-tag">input</span><span class="hljs-selector-class">.studentid</span><span class="hljs-selector-pseudo">:-ms-input-placeholder</span> { <span class="hljs-comment">/* Microsoft Edge */</span>
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#909090</span>;
}
</code></pre>
<p>The CSS code above targets placeholder text in input fields across browsers, sets their color to #909090, and ensures full opacity for consistent visibility (with specific rules for Microsoft Edge).</p>
<h3 id="heading-fonts">Fonts</h3>
<p>Fonts and typography face several cross-browser compatibility issues, from varying default font sizes to differences in font rendering engines. This can affect the weight, spacing, and overall appearance of text.</p>
<p>A font might appear thinner and more spaced out in Chrome compared to Edge, affecting readability and design consistency. </p>
<p>To resolve this:</p>
<ul>
<li>Define a base font size in your CSS and use relative units (like <code>em</code> or <code>rem</code>) for text sizing as shown in the code below. This helps maintain scalability and consistency.</li>
</ul>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">16px</span>; <span class="hljs-comment">/* Define a base font size */</span>
}

<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">font-family</span>: <span class="hljs-string">'Open Sans'</span>, sans-serif;
  <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1.6</span>;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#333</span>;
}

<span class="hljs-selector-tag">h1</span>, <span class="hljs-selector-tag">h2</span>, <span class="hljs-selector-tag">h3</span>, <span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">2rem</span>;;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">1.5rem</span>;
}
</code></pre>
<ul>
<li>When using web fonts, ensure they are loaded properly across all browsers by using services like Google Fonts, which provide cross-browser compatible font loading:</li>
</ul>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"&lt;https://fonts.googleapis.com/css?family=Open+Sans&amp;display=swap&gt;"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>&gt;</span>
</code></pre>
<ul>
<li>The code below makes sure that the 'Open Sans' font looks the same on our website, no matter the browser. It does this first by using a version of the font that might already be on our computer to load things faster. Otherwise, it grabs it from the internet but swaps in a default font while waiting for the latter to load. </li>
</ul>
<pre><code class="lang-css"><span class="hljs-keyword">@font-face</span> {
  <span class="hljs-attribute">font-family</span>: <span class="hljs-string">'Open Sans'</span>;
  <span class="hljs-attribute">font-style</span>: normal;
  <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">400</span>;
  <span class="hljs-attribute">font-display</span>: swap;
  <span class="hljs-attribute">src</span>: <span class="hljs-built_in">local</span>(<span class="hljs-string">'Open Sans Regular'</span>), <span class="hljs-built_in">local</span>(<span class="hljs-string">'OpenSans-Regular'</span>), <span class="hljs-built_in">url</span>(&lt;https://fonts.gstatic.com/s/opensans/v15/mem8YaGs126MiZpBA-UFVZ0b.woff2&gt;) <span class="hljs-built_in">format</span>(<span class="hljs-string">'woff2'</span>);
}
</code></pre>
<h3 id="heading-scrollbars">Scrollbars</h3>
<p>Scrollbar styling has long been a challenge for web developers due to inconsistent support across different browsers. While browsers like Chrome, Safari, and Edge have provided ways to customize scrollbars using CSS, the level of support and ways of implementing them vary.</p>
<p>Recent updates have seen improvements in standardizing scrollbar customization, with most modern browsers adopting similar capabilities. But there are still some differences in the approach:</p>
<p>For <strong>Chrome, Edge, and Firefox</strong>, you can use the CSS <code>scrollbar-width</code> and <code>scrollbar-color</code> properties to customize the scrollbar's appearance. These are part of a newer standard aimed at providing a more consistent way of styling scrollbars across browsers that support it.</p>
<pre><code class="lang-css"><span class="hljs-comment">/* For Chrome, Firefox, and Edge */</span>
<span class="hljs-selector-tag">scrollbar-width</span>: <span class="hljs-selector-tag">thin</span>;
<span class="hljs-selector-tag">scrollbar-color</span>: <span class="hljs-selector-id">#c0c0c0</span> <span class="hljs-selector-id">#f0f0f0</span>;
</code></pre>
<p><strong>For Safari</strong>, which uses the WebKit rendering engine, you'll need to use the <code>::-webkit-scrollbar</code> pseudo-element to achieve similar styling. This method is specific to WebKit-based browsers.</p>
<pre><code class="lang-css"><span class="hljs-comment">/* For Safari */</span>
<span class="hljs-selector-class">.mostly-customized-scrollbar</span><span class="hljs-selector-pseudo">::-webkit-scrollbar</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">5px</span>;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">8px</span>;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#aaa</span>; <span class="hljs-comment">/* or add it to the track */</span>
}
</code></pre>
<p>The CSS code above customizes the appearance of scrollbars across those browsers by adjusting their size and colours.</p>
<p>But for consistency across all browsers, you'll need to design your web pages in a way that the default scrollbar appearance does not negatively impact your design.</p>
<h2 id="heading-best-practices-for-cross-browser-compatibility">Best Practices for Cross-Browser Compatibility</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/best-practices.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>Infographic showing measuring tools. Image credit Creative Bloq</em></p>
<h3 id="heading-define-a-doctype">Define a Doctype</h3>
<p>Start your HTML document with a <code>&lt;!DOCTYPE&gt;</code> declaration to ensure standards mode is activated. </p>
<p>This is important because it tells the web browser which version of HTML the page is written in. Without it, browsers might render the page in "quirks mode," – where the browser assumes you've written old, non-standard code. This ultimately leads to unpredictable styling and layout issues because modern web standards are not fully applied.</p>
<p>A <code>&lt;!DOCTYPE&gt;</code> declaration in HTML5 looks like this at the very beginning of your HTML file:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
</code></pre>
<h3 id="heading-use-a-css-reset">Use a CSS Reset</h3>
<p>A CSS reset is basically adding a set of rules that target common elements to remove their default styling, reducing browser-default discrepancies. </p>
<p>Various browsers have different inherent styles for HTML elements – margins, paddings, font sizes, and so on. So implementing a CSS reset makes sure that only the styles you write in your code will take effect. This leads to a consistent baseline for styling your webpage across various browsers. </p>
<p>There are developers that like to write theirs from scratch. And there are others like me, who use <a target="_blank" href="https://meyerweb.com/eric/tools/css/reset/">Eric Meyer's popular and free CSS reset</a> as you can see in the code below:</p>
<pre><code class="lang-css"><span class="hljs-comment">/* http://meyerweb.com/eric/tools/css/reset/ 
   v2.0 | 20110126
   License: none (public domain)
*/</span>

<span class="hljs-selector-tag">html</span>, <span class="hljs-selector-tag">body</span>, <span class="hljs-selector-tag">div</span>, <span class="hljs-selector-tag">span</span>, <span class="hljs-selector-tag">applet</span>, <span class="hljs-selector-tag">object</span>, <span class="hljs-selector-tag">iframe</span>,
<span class="hljs-selector-tag">h1</span>, <span class="hljs-selector-tag">h2</span>, <span class="hljs-selector-tag">h3</span>, <span class="hljs-selector-tag">h4</span>, <span class="hljs-selector-tag">h5</span>, <span class="hljs-selector-tag">h6</span>, <span class="hljs-selector-tag">p</span>, <span class="hljs-selector-tag">blockquote</span>, <span class="hljs-selector-tag">pre</span>,
<span class="hljs-selector-tag">a</span>, <span class="hljs-selector-tag">abbr</span>, <span class="hljs-selector-tag">acronym</span>, <span class="hljs-selector-tag">address</span>, <span class="hljs-selector-tag">big</span>, <span class="hljs-selector-tag">cite</span>, <span class="hljs-selector-tag">code</span>,
<span class="hljs-selector-tag">del</span>, <span class="hljs-selector-tag">dfn</span>, <span class="hljs-selector-tag">em</span>, <span class="hljs-selector-tag">img</span>, <span class="hljs-selector-tag">ins</span>, <span class="hljs-selector-tag">kbd</span>, <span class="hljs-selector-tag">q</span>, <span class="hljs-selector-tag">s</span>, <span class="hljs-selector-tag">samp</span>,
<span class="hljs-selector-tag">small</span>, <span class="hljs-selector-tag">strike</span>, <span class="hljs-selector-tag">strong</span>, <span class="hljs-selector-tag">sub</span>, <span class="hljs-selector-tag">sup</span>, <span class="hljs-selector-tag">tt</span>, <span class="hljs-selector-tag">var</span>,
<span class="hljs-selector-tag">b</span>, <span class="hljs-selector-tag">u</span>, <span class="hljs-selector-tag">i</span>, <span class="hljs-selector-tag">center</span>,
<span class="hljs-selector-tag">dl</span>, <span class="hljs-selector-tag">dt</span>, <span class="hljs-selector-tag">dd</span>, <span class="hljs-selector-tag">ol</span>, <span class="hljs-selector-tag">ul</span>, <span class="hljs-selector-tag">li</span>,
<span class="hljs-selector-tag">fieldset</span>, <span class="hljs-selector-tag">form</span>, <span class="hljs-selector-tag">label</span>, <span class="hljs-selector-tag">legend</span>,
<span class="hljs-selector-tag">table</span>, <span class="hljs-selector-tag">caption</span>, <span class="hljs-selector-tag">tbody</span>, <span class="hljs-selector-tag">tfoot</span>, <span class="hljs-selector-tag">thead</span>, <span class="hljs-selector-tag">tr</span>, <span class="hljs-selector-tag">th</span>, <span class="hljs-selector-tag">td</span>,
<span class="hljs-selector-tag">article</span>, <span class="hljs-selector-tag">aside</span>, <span class="hljs-selector-tag">canvas</span>, <span class="hljs-selector-tag">details</span>, <span class="hljs-selector-tag">embed</span>, 
<span class="hljs-selector-tag">figure</span>, <span class="hljs-selector-tag">figcaption</span>, <span class="hljs-selector-tag">footer</span>, <span class="hljs-selector-tag">header</span>, <span class="hljs-selector-tag">hgroup</span>, 
<span class="hljs-selector-tag">menu</span>, <span class="hljs-selector-tag">nav</span>, <span class="hljs-selector-tag">output</span>, <span class="hljs-selector-tag">ruby</span>, <span class="hljs-selector-tag">section</span>, <span class="hljs-selector-tag">summary</span>,
<span class="hljs-selector-tag">time</span>, <span class="hljs-selector-tag">mark</span>, <span class="hljs-selector-tag">audio</span>, <span class="hljs-selector-tag">video</span> {
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">border</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">100%</span>;
    <span class="hljs-attribute">font</span>: inherit;
    <span class="hljs-attribute">vertical-align</span>: baseline;
}
<span class="hljs-comment">/* HTML5 display-role reset for older browsers */</span>
<span class="hljs-selector-tag">article</span>, <span class="hljs-selector-tag">aside</span>, <span class="hljs-selector-tag">details</span>, <span class="hljs-selector-tag">figcaption</span>, <span class="hljs-selector-tag">figure</span>, 
<span class="hljs-selector-tag">footer</span>, <span class="hljs-selector-tag">header</span>, <span class="hljs-selector-tag">hgroup</span>, <span class="hljs-selector-tag">menu</span>, <span class="hljs-selector-tag">nav</span>, <span class="hljs-selector-tag">section</span> {
    <span class="hljs-attribute">display</span>: block;
}
<span class="hljs-selector-tag">body</span> {
    <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1</span>;
}
<span class="hljs-selector-tag">ol</span>, <span class="hljs-selector-tag">ul</span> {
    <span class="hljs-attribute">list-style</span>: none;
}
<span class="hljs-selector-tag">blockquote</span>, <span class="hljs-selector-tag">q</span> {
    <span class="hljs-attribute">quotes</span>: none;
}
<span class="hljs-selector-tag">blockquote</span><span class="hljs-selector-pseudo">:before</span>, <span class="hljs-selector-tag">blockquote</span><span class="hljs-selector-pseudo">:after</span>,
<span class="hljs-selector-tag">q</span><span class="hljs-selector-pseudo">:before</span>, <span class="hljs-selector-tag">q</span><span class="hljs-selector-pseudo">:after</span> {
    <span class="hljs-attribute">content</span>: <span class="hljs-string">''</span>;
    <span class="hljs-attribute">content</span>: none;
}
<span class="hljs-selector-tag">table</span> {
    <span class="hljs-attribute">border-collapse</span>: collapse;
    <span class="hljs-attribute">border-spacing</span>: <span class="hljs-number">0</span>;
}
</code></pre>
<p>There's another group of developers that use <a target="_blank" href="https://necolas.github.io/normalize.css/">Normalize.css</a>, which you can install using a package manager like npm and then importing it in your CSS.</p>
<pre><code class="lang-bash">npm install normalize.css
</code></pre>
<h3 id="heading-review-css-property-support">Review CSS Property Support</h3>
<p>Before using advanced CSS features, check their compatibility on websites like <a target="_blank" href="https://caniuse.com/">Can I Use</a>. There, you can find detailed compatibility tables for HTML, CSS, and JavaScript features across different browsers and versions. This should help you make informed decisions about which technologies to use and when to implement fallbacks.</p>
<p>In the screenshot below, I searched for CSS Grid and immediately got to see the various browsers and their versions that support it. So before implementing CSS Grid on my web page, I have an idea of the browsers that it works with.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Screenshot-2024-03-05-at-9.06.17-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Browser compatibility for CSS Grid.</em></p>
<h3 id="heading-create-responsive-websites">Create Responsive Websites</h3>
<p>The multi-device world we currently live in demands that, as web developers, we make responsiveness a priority. </p>
<p>We can use fluid layouts, flexible images, and media queries to ensure our websites adapt to any screen size. The ripple effects of getting responsiveness right is cross-browser compatibility, accessibility and enhanced user experience.</p>
<p><a target="_blank" href="https://www.freecodecamp.org/news/responsive-design-best-practices/">Here's an article</a> discussing some best practices for responsive design and how to implement them.</p>
<h3 id="heading-do-cross-browser-testing">Do Cross-Browser Testing</h3>
<p>Testing has become such a buzzword in programming lately, but this is because it's very important to make sure the code you write works as expected. </p>
<p>It's not just about checking if your TypeScript code runs smoothly, though. Even simpler web projects need thorough testing. </p>
<p>Cross-browser testing means trying your web pages on various browsers and devices to make sure they look and work consistently across board.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Cross-browser compatibility may be a mouthful to pronounce. But as we’ve seen, it's essential to consider when building websites. And you can gradually make your websites compatible by testing and tweaking your code and implementing some of the five best practices we’ve discussed above. </p>
<p>So, before you draw the curtains on your next website or web app, remember to check if your users on Chrome, Firefox, Safari, and other browsers are seeing and experiencing the same things.</p>
<p>Here are some helpful resources:</p>
<ul>
<li><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Introduction">MDN Web Docs on Cross-browser compatibility</a></li>
<li><a target="_blank" href="https://medium.com/@codepaper_/the-significance-of-cross-browser-compatibility-in-website-development-8ea2cca480dc">Codepaper on Significance of Cross-browser compatibility</a></li>
<li><a target="_blank" href="https://meyerweb.com/eric/tools/css/reset/">Eric Meyer on CSS Reset</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Cross-Browser Compatibility Testing – Best Practices for Web Developers ]]>
                </title>
                <description>
                    <![CDATA[ Imagine putting in a ton of work to build a web application. And then it works in the Chrome browser, but misbehaves in Mozilla, Safari, or any other browser. As a web developer, you're likely eager to create amazing web applications that reach users... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/cross-browser-compatibility-testing-best-practices-for-web-developers/</link>
                <guid isPermaLink="false">66d45e01264384a65d5a9508</guid>
                
                    <category>
                        <![CDATA[ Browsers ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Compatibility ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Casmir Onyekani ]]>
                </dc:creator>
                <pubDate>Thu, 05 Oct 2023 23:40:10 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/10/cross-browser-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Imagine putting in a ton of work to build a web application. And then it works in the Chrome browser, but misbehaves in Mozilla, Safari, or any other browser.</p>
<p>As a web developer, you're likely eager to create amazing web applications that reach users across the globe. But one major challenge you'll face is ensuring that your web app works seamlessly on various web browsers. This is where cross-browser compatibility testing comes into play.</p>
<p>In this article, we'll dive into the challenges of cross-browser compatibility, and I'll give you some best practices to overcome them.</p>
<h2 id="heading-what-is-cross-browser-compatibility-testing">What is Cross-Browser compatibility testing?</h2>
<p>Cross-browser compatibility testing is a critical quality assurance process in web development. It involves testing and ensuring that a website or web application functions and appears consistently and correctly across different web browsers and their various versions.</p>
<p>Since web browsers are developed by different companies and have distinct rendering engines, they may interpret HTML, CSS, and JavaScript code differently. This can lead to discrepancies in how a website looks and behaves, causing issues for users who access the site using different browsers.</p>
<h2 id="heading-common-cross-browser-compatibility-issues">Common Cross-Browser Compatibility Issues</h2>
<p>One fundamental cross-browser compatibility concern relates to the rendering of web pages.</p>
<p>CSS styles add another layer of complexity. Inconsistencies in how browsers interpret and apply these styles can lead to visual disparities, such as variations in font sizes, colors, spacing, and layout. These discrepancies can undermine the website's design integrity and user experience.</p>
<p>Plugins like Flash or Java pose compatibility challenges, as not all browsers support them, and some browsers have disabled them entirely. This can result in certain features of a website not working as intended or being inaccessible to users on specific browsers.</p>
<p>Web developers often rely on third-party libraries and frameworks to streamline development. But these dependencies may not be universally compatible with all browsers.</p>
<p>Compatibility issues with these external tools can lead to malfunctions or performance bottlenecks, affecting the website's overall stability and functionality.</p>
<p>Browser-specific bugs related to form submission, caching, and other critical functions can create headaches for developers. These bugs may manifest differently on each browser, requiring meticulous testing and workarounds to ensure consistent performance and functionality across the board.</p>
<h2 id="heading-differences-between-cross-browser-and-compatibility-testing">Differences Between Cross-Browser and Compatibility Testing</h2>
<p>There are some key differences between cross-browser testing and compatibility testing. Here are the main ones:</p>
<h3 id="heading-scope">Scope</h3>
<p>Cross-browser testing focuses on ensuring that a website or web application functions consistently and correctly across different web browsers. It primarily addresses variations in rendering and behavior caused by different browsers' rendering engines.</p>
<p>Compatibility testing is a broader testing approach that encompasses not only different browsers but also various operating systems, devices, screen sizes, and network conditions. It assesses how well a website or application functions across a range of diverse environments.</p>
<h3 id="heading-objective">Objective</h3>
<p>The main objective of cross-browser testing is to verify that the website or web app looks, works, and behaves the same or very similarly across various browsers, such as Google Chrome, Mozilla Firefox, Apple Safari, Microsoft Edge, and others. It aims to eliminate visual discrepancies, functional issues, and inconsistencies in user experience.</p>
<p>The primary goal of compatibility testing is to ensure that the website or application is compatible with a wide array of user environments, such as browsers, operating systems (Windows, macOS, Android, iOS), devices (desktops, laptops, tablets, smartphones), and network conditions (internet speeds and connectivity types).</p>
<h3 id="heading-challenges">Challenges</h3>
<p>Challenges in cross-browser testing arise from variations in how browsers interpret HTML, CSS, and JavaScript code, as well as differences in supported features and standards compliance.</p>
<p>Challenges in compatibility testing include addressing issues related to device-specific features, operating system dependencies, and network-related performance problems in addition to cross-browser challenges.</p>
<p>In summary, cross-browser testing is a subset of compatibility testing. While cross-browser testing specifically focuses on ensuring consistent performance across different web browsers and versions, compatibility testing encompasses a wider range of factors, including browsers, operating systems, devices, and network conditions. This helps guarantee a seamless user experience across diverse user environments.</p>
<p>Both types of testing are crucial for delivering high-quality web applications that meet the needs of a broad user base.</p>
<h2 id="heading-importance-of-cross-browser-compatibility-testing">Importance of Cross-Browser Compatibility Testing</h2>
<p>Neglecting this crucial aspect of web development can result in missed opportunities and potential damage to your brand's reputation.</p>
<h3 id="heading-user-experience">User Experience</h3>
<p>Users access websites and web applications through a variety of browsers and devices. Ensuring compatibility across these platforms guarantees a consistent and seamless experience for all users.</p>
<p>Frustration resulting from a poorly rendered website on a specific browser can lead to a high bounce rate and loss of potential customers or visitors.</p>
<h3 id="heading-market-reach">Market Reach</h3>
<p>Different users prefer different web browsers. Ignoring compatibility testing means potentially alienating a significant portion of your audience.</p>
<p>By ensuring your website works well on popular browsers like Chrome, Firefox, Safari, and Edge, you maximize your market reach and accessibility.</p>
<h3 id="heading-maintaining-credibility">Maintaining Credibility</h3>
<p>A website that functions well across browsers reflects professionalism and attention to detail. On the contrary, a website with compatibility issues can harm your brand's credibility and reputation. Users might perceive your site as unreliable or poorly developed.</p>
<h3 id="heading-mobile-devices">Mobile Devices</h3>
<p>Mobile browsers come with their own set of quirks and challenges. Given the rise in mobile internet usage, ensuring compatibility with mobile browsers is crucial.</p>
<p>A website that adapts well to varying screen sizes and touch interfaces is essential for catering to the mobile audience.</p>
<h3 id="heading-seo-impact">SEO Impact</h3>
<p>Search engines like Google consider user experience as a ranking factor. If your website performs poorly on specific browsers, it might affect your search engine rankings. A lower search ranking can significantly reduce organic traffic to your site.</p>
<h3 id="heading-support-and-maintenance">Support and Maintenance</h3>
<p>A website that works smoothly across different browsers reduces the burden of ongoing support and maintenance. Fewer compatibility-related issues mean fewer updates and patches needed, saving time and resources in the long run.</p>
<h3 id="heading-accessibility-compliance">Accessibility Compliance</h3>
<p>Accessibility is not only a legal requirement in many regions but also a moral imperative. Ensuring compatibility with screen readers and other assistive technologies allow people with disabilities to access and use your website.</p>
<p>Failure to meet accessibility standards can lead to legal consequences and damage to your brand's reputation.</p>
<h3 id="heading-global-audience">Global Audience</h3>
<p>The internet connects people worldwide. International users will access your website using various browsers. Cross-browser compatibility ensures that language characters, fonts, and other regional aspects display correctly, enabling you to cater to a global audience effectively.</p>
<h3 id="heading-competitive-advantage">Competitive Advantage</h3>
<p>Websites that prioritize cross-browser compatibility gain a competitive edge. They can attract and retain users more effectively than those with compatibility issues.</p>
<p>A well-optimized site provides a better user experience, leading to higher user engagement and potentially higher conversion rates.</p>
<h2 id="heading-types-of-cross-browser-compatibility-testing">Types of Cross-Browser Compatibility Testing</h2>
<p>Here are some of the main types of cross-browser and compatibility testing:</p>
<h3 id="heading-functional-testing">Functional Testing</h3>
<p>This type of testing checks if all the interactive features and functionalities of a website work as expected across different browsers.</p>
<p>Examples are ensuring that forms can be submitted, buttons are clickable, navigation menus function correctly, and scripting interactions behave consistently.</p>
<h3 id="heading-visual-testing">Visual Testing</h3>
<p>This type of testing focuses on the visual appearance of a website or application across different browsers and devices.</p>
<p>Examples are verifying that fonts, colors, layouts, and images are displayed consistently, and that there are no visual glitches or misalignments.</p>
<h3 id="heading-performance-testing">Performance Testing</h3>
<p>This type of testing assesses how a website performs in terms of loading speed and responsiveness across various browsers and devices.</p>
<p>Examples are measuring page load times, checking the site's responsiveness on different screen sizes, and ensuring that resource-intensive features (videos or animations) do not cause performance issues.</p>
<h3 id="heading-cross-device-testing">Cross-Device Testing</h3>
<p>This type of testing ensures that a website functions properly on a range of devices, including desktops, laptops, tablets, and mobile phones.</p>
<p>Examples are testing touch interactions on mobile devices, verifying responsiveness on different screen resolutions, and confirming compatibility with various device orientations (landscape and portrait).</p>
<h3 id="heading-cross-platform-testing">Cross-Platform Testing</h3>
<p>This type of testing involves checking compatibility across different operating systems and browsers.</p>
<p>Example is to verify that the website functions consistently on both Windows and macOS computers, as well as Android and iOS devices.</p>
<h3 id="heading-browser-version-testing">Browser Version Testing</h3>
<p>This type of testing involves testing a website on different versions of a particular browser to ensure compatibility across various iterations.</p>
<p>An example is to test on older versions of popular browsers like Internet Explorer 11, or older versions of Firefox or Chrome, to support users who have not updated their browsers.</p>
<h3 id="heading-accessibility-testing">Accessibility Testing</h3>
<p>This type of testing helps ensure that a website is usable by people with disabilities and complies with accessibility standards such as WCAG (Web Content Accessibility Guidelines).</p>
<p>Examples are testing keyboard navigation, screen reader compatibility, and the use of ARIA (Accessible Rich Internet Applications) attributes to make the site more accessible to users with disabilities.</p>
<h3 id="heading-security-testing">Security Testing</h3>
<p>Security testing verifies that a website's security features and protocols work consistently across different browsers and platforms.</p>
<p>Examples are to ensure that SSL (Secure Sockets Layer) certificates are correctly implemented, that login forms are secure, and that security headers like Content Security Policy (CSP) are effective.</p>
<p>This comprehensive testing approach helps ensure a seamless and consistent user experience across diverse user environments.</p>
<h2 id="heading-roles-and-collaboration-in-cross-browser-compatibility-testing">Roles and Collaboration in Cross-Browser Compatibility Testing</h2>
<p>Cross-browser compatibility testing involves web developers, designers, and quality testers working together. Developers write clean code, designers ensure visual consistency, and testers find and document issues.</p>
<p>Collaboration is key. Developers and designers create flexible designs, and testers rely on their expertise. Communication is vital for resolving issues promptly and meeting compatibility standards.</p>
<p>External collaboration with users and clients is also crucial. User feedback helps identify real-world issues, and managing client expectations aligns with browser capabilities. Successful testing relies on technical know-how and a collaborative culture within the team and with external stakeholders.</p>
<h2 id="heading-best-practices-for-cross-browser-compatibility-testing">Best Practices for Cross-Browser Compatibility Testing</h2>
<p>By adhering to these best practices, web developers and testers can effectively tackle cross-browser compatibility challenges and deliver web experiences that are reliable and user-friendly across a wide range of browsers and devices.</p>
<ul>
<li><p>Identify Target Browsers: Determine which browsers are most commonly used by your target audience. Focus your testing efforts on these browsers to ensure the best user experience for the majority of your visitors.</p>
</li>
<li><p>Prioritize Popular Browsers: Give higher priority to testing on the most popular web browsers such as Google Chrome, Mozilla Firefox, Apple Safari, and Microsoft Edge. These browsers have larger user bases and are more likely to be used by your visitors.</p>
</li>
<li><p>Test on Mobile Devices: Don't forget to test on mobile browsers, including iOS Safari and Android Chrome, as mobile users make up a significant portion of internet traffic. Ensure that your website is responsive and mobile-friendly.</p>
</li>
<li><p>Use Browser Developer Tools: Familiarize yourself with the developer tools available in modern browsers. These tools allow you to inspect elements,<br>  debug JavaScript, and simulate different browser environments, making it easier to identify and fix issues.</p>
</li>
<li><p>Leverage Cross-Browser Testing Tools: Consider using cross-browser testing tools and services like BrowserStack, CrossBrowserTesting, or Sauce Labs.<br>  These platforms provide access to a wide range of browser and OS combinations, allowing you to test efficiently without setting up multiple physical environments.</p>
</li>
<li><p>Regularly Update Your Browser List: Keep your list of target browsers up to date. Browsers release new versions regularly, and older versions may become less relevant. Test on the latest browser versions to address potential issues before they become widespread.</p>
</li>
<li><p>Validate HTML and CSS: Use validation tools such as the <a target="_blank" href="https://validator.w3.org/">W3C Markup Validation Service</a> and <a target="_blank" href="https://www.cssportal.com/css-validator/">CSS Validator</a> to check your code for compliance with web standards. Valid code is more likely to render consistently across browsers.</p>
</li>
<li><p>Implement Graceful Degradation and Progressive Enhancement: Design your website with a "baseline" experience that works on all browsers and devices. Then, enhance the experience for modern browsers with additional features.<br>  This approach ensures that all users have a functional experience.</p>
</li>
<li><p>Perform Automated Testing: Consider setting up automated testing using tools like <a target="_blank" href="https://www.selenium.dev/">Selenium</a>, <a target="_blank" href="https://pptr.dev/">Puppeteer</a>, or <a target="_blank" href="https://testcafe.io/">TestCafe</a>. These tools allow you to create and run test scripts across various browsers automatically, saving time and ensuring consistency.</p>
</li>
<li><p>Regularly Review and Update: Stay informed about the latest developments in web standards, browser updates, and best practices. Periodically review and update your testing procedures to remain effective in ensuring cross-browser compatibility.</p>
</li>
<li><p>Test Accessibility: Ensure that your website complies with web accessibility standards, such as WCAG. Test with screen readers and other assistive technologies to make your site accessible to users with disabilities.</p>
</li>
<li><p>Document and Track Issues: Maintain a detailed log of cross-browser compatibility issues and their resolutions. This documentation will help your team address similar issues in the future and maintain a high level of consistency.</p>
</li>
</ul>
<h2 id="heading-tools-for-cross-browser-testing">Tools for Cross-Browser Testing</h2>
<p>You have access to various tools that can help you test your web projects efficiently. Let's look at a few popular ones now:</p>
<h3 id="heading-browserstack">BrowserStack</h3>
<p>This is a popular cloud-based cross-browser testing platform that allows you to test your website or web app on a wide range of browsers and operating systems.</p>
<p>It provides access to real browser instances for manual testing and supports automated testing with Selenium and Appium.</p>
<h3 id="heading-crossbrowsertesting">CrossBrowserTesting</h3>
<p>This is a cloud-based testing platform that offers a vast array of browsers and devices for cross-browser testing.</p>
<p>It provides live interactive testing as well as automated testing capabilities and integrates with various testing frameworks.</p>
<h3 id="heading-sauce-labs">Sauce Labs</h3>
<p>This is another cloud-based testing platform that offers a comprehensive range of browser and device combinations for testing web and mobile applications.</p>
<p>It supports both manual and automated testing and integrates with popular testing frameworks like Selenium and Appium.</p>
<h3 id="heading-lambdatest">LambdaTest</h3>
<p>This is a cloud-based cross-browser testing platform that provides access to a large selection of browsers and operating systems.</p>
<p>It offers live interactive testing and supports automated testing with popular testing frameworks.</p>
<h3 id="heading-browserling">Browserling</h3>
<p>This is a web-based tool that allows you to quickly test your website on a variety of browsers without the need for downloads or installations.</p>
<p>It offers real-time browser access and is suitable for quick checks and debugging.</p>
<h3 id="heading-browsershots">Browsershots</h3>
<p>This is an open-source tool that provides screenshots of your website or web app as it appears in different browsers and versions. While it doesn't offer live testing or interaction, it's useful for visual comparisons.</p>
<h3 id="heading-blisk">Blisk</h3>
<p>This is a browser specifically designed for web development and testing. It provides a side-by-side view of your website in multiple devices and browsers, making it easier to spot compatibility issues during development.</p>
<h3 id="heading-ghostlab">Ghostlab</h3>
<p>This is a paid tool for synchronized testing and debugging across multiple devices and browsers. It helps you inspect and debug issues in real time while maintaining synchronization between devices.</p>
<h3 id="heading-browser-devtools">Browser DevTools</h3>
<p>Most modern browsers, including Chrome, Firefox, Safari, and Edge, come with built-in developer tools. These tools are essential for inspecting, debugging, and testing websites directly in the browser environment. They offer features for emulating different browsers, devices, and network conditions.</p>
<p>These tools vary in terms of features, pricing, and ease of use, so it's essential to choose the one that best fits your specific cross-browser testing needs and budget.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Cross-browser compatibility testing is an essential aspect of web development. By following these best practices, you can ensure that your web applications provide a consistent and delightful user experience across different browsers.</p>
<p>A combination of cloud-based testing platforms and browser developer tools can provide comprehensive coverage for testing your web projects on different browsers and ensuring a consistent user experience.</p>
<p>Remember that the web development field is constantly changing, so continuous learning and adaptation are key to your success.</p>
<p>If you found this guide helpful and enjoyable, please give it a like. For more insightful tutorials, follow me on <a target="_blank" href="https://twitter.com/casweb_dev">X</a> for updates <strong>🙏</strong>.</p>
<p>Happy coding, and may your web apps thrive in every corner of the internet!</p>
<p>Kudos to ValueCoders for the cover image image.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ API stability is cheap and easy, with Compat Patchers! ]]>
                </title>
                <description>
                    <![CDATA[ By Pakal de Bonchamp Why backwards compatibility matters (If you're already convinced that API stability is a crucial concern, not the whim of a few conservative mummies, save yourself some time and rush to the following chapter.) "WE DO NOT BREAK U... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/api-stability-is-cheap-and-easy/</link>
                <guid isPermaLink="false">66d4608bd7a4e35e384349a5</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ best practices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Compatibility ]]>
                    </category>
                
                    <category>
                        <![CDATA[ patching ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ stability ]]>
                    </category>
                
                    <category>
                        <![CDATA[ versioning ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 28 Jun 2019 21:00:40 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/06/windowsserver_article_012-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Pakal de Bonchamp</p>
<h2 id="heading-why-backwards-compatibility-matters">Why backwards compatibility matters</h2>
<p><em>(If you're already convinced that API stability is a crucial concern, not the whim of a few conservative mummies, save yourself some time and rush to the following chapter.)</em></p>
<blockquote>
<p>"WE DO NOT BREAK USERSPACE!"</p>
</blockquote>
<p>This <a target="_blank" href="https://lkml.org/lkml/2012/12/23/75">famous rant of Linus Torvalds</a> is, alas, more relevant than ever.</p>
<blockquote>
<p>If a change results in user programs breaking, it's a bug in the kernel. We never EVER blame the user programs. How hard can this be to understand?</p>
<p>If applications didn't care about specific error values, then it wouldn't make sense to have more than one to begin with, and you shouldn't care which one that was. But since applications <em>do</em> care, and since we <em>do</em> have multiple error values, we stick to the old ones, unless there are some <em>very</em> good reasons not to. And those reasons really need to be very good, and spelled out and explained.</p>
</blockquote>
<p>Let's replace "kernel" by any framework/library, and "error value" by "API signature", and we get an invaluable commandment of good programming. We can live quite well with a few buglets and imperfect features, but when our applications deliver segfaults or lengthy tracebacks after a simple version upgrade, there is a problem. A real problem.</p>
<p>And there is a paradox here. Regarding OS distributions, drivers, libc/gtk/Qt and other low-level, statically typed libraries, we expect - and are happy to experience - painless updates, bringing only new features and bugfixes. Whereas for our high-level web frameworks, mostly coded in dynamic languages, we have become resigned to the fact that each update could become a 3-days labor of understanding breakages, finding compatible versions of dependencies, and forking or monkey-patching until test suites are green again. Logically, shouldn't it be the other way round ? Why are most 1995 win32 freewares still working, why was the x32/x64 migration so transparent for most users, if a pluggable server app released 2 years ago is broken on multiple aspects?</p>
<p>I'll tell you why. </p>
<p>API stability was once a very praised commitment. Semantic versioning was a must-have. Projects like Qt proudly detailed the measures they took to ensure their C/C++ would evolve without breakage. Some even filled their function parameters with NULL values "reserved for future uses". And incompatible changes were only evocated when no solution could be found.</p>
<p>Luckily, this mindset is still valid in large areas of programming. But now a different philosophy has contaminated minds, especially in the web industry. This spartan way of thinking could be called "Walk or die", "No paradise for the weak", or "As long as I warn, I can shoot the bullet". Sometimes hiding behind cute concepts like "calendar versioning", or "evergreen applications", this way of thinking is actually crystal-clear: the most minor software upgrade may introduce breaking changes - documented or not, proudly assumed or not -  just deal with it.</p>
<p>Why? Why not just let aliases, adapters, and other compatibility shims, when moving modules around, when renaming objects, when changing function signatures? With the dynamic and introspective nature of most modern languages,  isn't that a breeze? Sometimes development resources are so scarce that it's already too much. But the rest of the time? My guess is that when it is not a problem of technical skill, or of laziness, it might be a cultural issue.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/06/meme_bill.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Do you know this dopamine hit you get when you tick a box in a checklist, especially the last one? This satisfaction that sometimes makes you write an already completed task <em>just so you can tick it</em>? You might get the same thrill when you brutally refactor code to a cleaner architecture, or erase compatibility shims "<em>as per deprecation policy</em>". It's the happiness rush of the duty well done, of the return to purity. </p>
<p>But this precise feeling is a huge lie. A blinding self-absorption. A harmful psychological bias.</p>
<p>Compatibility shims are not technical debt; nor a set of warts. At the very contrary, they are invaluable assets. With these few chunks of source code, our software extends its compatibility to tens, hundreds, thousands of miscellaneous libraries and applications spread across the web, in both public and private repositories, ranging from tiny utilities to huge corporate applications. These foreign codebases, full of business logic, of money-bringing features, of highly specific code, are what make their foundations worth existing. </p>
<p>But this ecosystem is of an extraordinary diversity. Some repositories get commits every day from multiple contributors, some get a mass update once in a while when their maintainers get a little spare time, and some have not been touched for years (because their creator lost interest, or just couldn't find anything to improve). Some have Tox-like multi-version testing and continuous integration, some don't even have a single unit-test. </p>
<p>So what happens when developers follow this trendy "Walk or die" philosophy? The ecosystem, already heavily fragmented by language (python2vs3, ruby, go, php... just for dynamic languages), by file format and network protocol, by framework and execution style (sync vs async), gets fragmented even more. In the most silent and deadly way. Basically, if we consider the codebases depending on a framework or library (here called "the software"): </p>
<ul>
<li>Repositories that haven't been updated for a few years are broken by default.</li>
<li>Repositories that are actively maintained, but do not target the same software version as us, do not work either.</li>
<li>Bug trackers get filled with useless "Plz add support for version X.Y.Z" or "Plz restore support for version X.Y.Z" tickets.</li>
<li>Forks flourish around mildly renowned repositories ; forks which can't be merged back, since each of their modifications are highly likely to break things for other software versions ; and the subsequent improvements brought by each forker, being chained to divergent codebases, keep spreading without ever being merged back ; naturally, they get remade by several developers each on his own, since few of them take the time to review the forks graph and cherry-pick interesting commits.</li>
<li>Biggest projects sometimes get nice enough to provide a compatibility matrix, or "known working sets" pinned down to their patch version number. But as soon as you have more than a few dependencies, you enter a dependency hell that no conflict resolution algorithm can tackle ; you just have to fork, fork, fork, and monkey-patch, until your dependencies find an agreement.</li>
<li>Project requirements get filled with links to git repository and commit hashes; semantic-less data which will make the next upgrades still more awkwardly experimental; or which will disappear due to an unexpected "force-push".</li>
<li>Without surprise, many maintainers of these pluggable apps don't want to take on them the additional burden of filling their code with special cases, to work around the breakage frenzy of the main software's developers. As a result, the dependency hell keeps expanding unrestrained.</li>
</ul>
<p>So when proudly pluralizing the name of a submodule, when removing a purportedly little-used utility class, when making an optional argument become mandatory, we're not improving anything. We're just murdering practicality for the sake of aesthetical purity. We're recklessly destroying entire regions of the software ecosystem, turning gazillions of test suites into reddish nightmares. But we'll never know to what extent; especially if we don't check. Ignorance is bliss.</p>
<p>Biological ecosystems can reach down to the depth of the abyss or to other planets if they have plenty of time; when things change too quickly, it's mass extinction. Software ecosystems are no different. Enjoying the cleanliness of an API "remade from scratch" is like enjoying the microbial sterility of a forest vitrified by a nuclear blast. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/06/meme_cant_break_compat.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>For sure, it's a falsehood to think that because we use some open-source software, we're entitled to getting the bugfixes and features that we request. But it's equally false to think that because the users of our framework/library are not paying clients, we owe them nothing. They trusted us, built their own code against ours, followed our conventions and best practices, when they could have chosen another language/framework/library. How can we justify trampling their own efforts, making them waste days or weeks of development, just because we suddenly felt the irrepressible urge to change a naming scheme, or drop perfectly working code? We're all interdependent in a software ecosystem, and a tiny dose of awareness, carefulness and rationality can go a long way. "<em>But you're never sure that a change doesn't break things</em>", some will shrug. Sure. No one demands perfection. But not being deliberately harmful is already a very good start. </p>
<p>There is like a paternalistic mood behind some advocates of the "walk or die" approach. "<em>If we stick to API stability, contributors will get lazy and never update their modules, the ecosystem will rot in place instead of moving forward</em>". Oh damn, how dangerous it is, to do people's good against their will. If we want users to update their codebase, at the very contrary, we should start by not brutally breaking things. We should bring shiny new features, not just a gun to their head. We should let them fix mildly annoying "deprecation warnings" when they feel like and can, not <strong>right now</strong>. We should let them spend their time on useful contributions, not on repairing what we have broken with the planned obsolescence that we dare calling "progress". </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/06/Compatibility-of-Hardware-and-Software.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Fun facts: advertising breaking changes in release notes does not grant them legitimacy; and when a private API is so handy that it's used by multiple projects, maybe it's a sign that it should be made public and documented, not that it should be wrecked at the first impulse.</p>
<p>So let's carve it into the marble of our desktops: API stability is, must be, on top of our list of concerns; along with robustness and adequation with final users' needs; but infinitely above any kind of aesthetical consideration. Only with long-term compatibility may our software ecosystems grow from a short elite of continually updated applications, to a huge and diverse galaxy of modules; some last- updated yesterday, some last-updated ten years ago, but all of them <strong>getting stuff done</strong>. Because that what software is all about, and that's what people are being paid for, at the end of the day. Not wasting time fixing the wheel that worked yesterday, and won't tomorrow ever more, because we heard the calling of the void.</p>
<h2 id="heading-the-compat-patcher-concept">The Compat Patcher concept</h2>
<p>Am I asking (open source) software maintainers to make more efforts, in order to achieve this so crucial long-term API stability? Nope. I wouldn't dare. At the contrary, I ask them to be lazier. But the good, the sensible, the both self-interested and benevolent, kind of lazy.</p>
<p>More compatibility means less support requests, less time justifying controversial changes, and more feature/bugfix contributions from our community. More compatibility doesn't even mean more keyboard typing. Except if we're only into toy projects, we've already put compatibility shims in place for a time. Just one thing to do : <strong>leave them be</strong>. They don't hurt us. They don't waste disk space. They are probably worth thousands of dollars per character. Let's just avoid one savage "Removing compatibility shim XYZ" commit, and move on towards greater goals.</p>
<p>And if the mere view of a compatibility shim makes us vomit (a not so unusual pathology I guess), there is awesome news : with high-level languages, we don't need shims in our code anymore. We just have to embrace the concept of <strong>Compatibility Patcher</strong> (or "compatcher" for neologism lovers).</p>
<p>Wat-iz-dat ? Just a companion library, often living its own life in its own repository, which plugs itself to the real software at startup time, and restores its compatibility with a decade of its previous versions. Thus, we can keep our codebase entirely unaware of whatever a "deprecation" might be, while still keeping a symbiotic coexistence with the thousands modules living in our ecosystem.</p>
<p>Monkey-patching is ugly, someone said? Maybe, but never as ugly as spending hours retro-engineering a whole plugin architecture, just to realize that an additional "S" in naming conventions sufficed to ruin everything. Programming overlords might prefer to weave their code with external shims using <a target="_blank" href="https://en.wikipedia.org/wiki/Aspect-oriented_programming">aspect-oriented programming</a>, but for most of us mere mortals, simplicity and pragmatism are widely sufficient enough. Some documentation, logging, and console warnings, are "explicit" enough to make anybody keep control over the codebase.</p>
<p>Let's not underestimate the power of high level languages. Examples with Python. We rename a submodule? Fine, thanks to import hooks, "<em>from framework import oldmodule</em>" and "<em>from framework import newmodule</em>" will return the exact same object. We change the signature of a function ? One tiny injection later, the old set of call parameters will automatically be adapted and forwarded to the new signature. We move an entire group of utilities out of the main repository? Fine, but as long as needed, the compatibility patcher will fetch them from their new location, and inject them back where they once so nicely belonged. We rename constants, classes, functions ? Leaving an alias was only costing a single code line, now with compatibility patchers this line doesn't even have to hurt our eyes and hearts anymore.</p>
<p>Please notice, Compatibility Patchers act like time travelers. They work even when developers delete a function, re-add it under a different shape, then remove it again. They work even when developers recklessly modify function behaviours, for example by exchanging similar arguments in-place. So imagine when developers cooperate with this system, and nicely decouple programming concerns so that the patch is minimal!</p>
<p>Cherry on the cake, by separating "state of art" code and compatibility shims, Compat Patchers make it a breeze to <strong>selectively activate compatibility sets</strong>. Your project is brand new and only relies on bleeding edge libraries ? Fine, deactivate the whole patcher. You just need compatibility with the last two major versions of the framework? Just enable the corresponding families of shims. You need support for very old packages ? Leave the patcher configuration in maximal mode.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/06/unicorn-deviant.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>That feeling when all 30 dependencies work smoothly on first install</em></p>
<p>Now comes the anxiety-provoking part : what are the downsides of Compat Patchers? Answer: up to a few seconds of delay at startup (when all shims are activated), and a few logical operations and type checks here and there at runtime. That's it. In the modern web world, where most server processes run for hours uninterrupted, process the most unoptimized (text-based) formats conceivable, and where performance depends much more on DB optimization and proper caching than on raw execution speed, it sounds like a legitimate expense, doesn't it?</p>
<p><em>Edit</em>: another limitation of Compat Patchers is that they require a tiny little bit of cooperation from core developers. Indeed, we all implicitly know the rule of backwards compatibility: "<strong>Only Add Optiona</strong>l". Add new optional arguments, add new functions, add new modules; don't remove elements and behaviours, don't make old options mandatory. But there is an additional, golden rule: <strong>don't ever, ever, change the semantic of things in-place</strong>. If we change the meaning of an argument, the format of an output, the action of a callable, without any additional indicator, then setting up shims becomes (almost) unfeasible; in this case, even Compat Patchers won't be able to resolve this ambiguity, and guess the behaviour that our users were requesting when using our API. Let's blacklist forever these kinds of <a target="_blank" href="https://docs.djangoproject.com/en/2.2/releases/2.2/#admin-actions-are-no-longer-collected-from-base-modeladmin-classes">brutal</a> and <a target="_blank" href="https://serverfault.com/questions/829754/why-did-the-format-of-nginx-ssl-client-i-dn-suddenly-change">inimical</a> changes.</p>
<h2 id="heading-time-for-practice">Time for practice!</h2>
<p>Compat patchers are not just wishful thinking. </p>
<p><a target="_blank" href="https://github.com/pakal/django-compat-patcher">Here is one</a> for the famous Django web framework. With a few dozens of small fixers, it allows one to use pluggable apps targeting from versions 1.6 to 2.2 of the framework. And it's only a start - feature requests and comments are welcome. </p>
<p>This patcher is used in production on a few sites, including the <a target="_blank" href="https://github.com/ChrysalisTeam/pychronia">Pychronia</a> portal and its CMS/Blog ecosystem. It runs on <a target="_blank" href="https://github.com/pakal/compat-patcher-core">CompatPatcherCore</a>, a Python micro-framework for creating such companion applications in the blink of an eye (a <a target="_blank" href="https://compat-patcher-core.readthedocs.io/en/latest/startup.html">cookiecutter recipe</a> is even included). </p>
<p>Without surprise, I warmly encourage you to bootstrap a Compat Patcher for the framework/library you might maintain, unless you are one of the few valiant minds already strongly committed to API stability.</p>
<p>This concept should also be easy to port to Ruby, PHP, Javascript, and other high-malleability languages. With lower-level and static languages, the task might be much harder (and require macro processors and the likes), but who knows.</p>
<p><strong>So here we are. Update breakages are not a fatality. Just a bad habit that we must <em>break</em>, thanks to a little pondering and a few technical niceties. We may thus enjoy the delights of ever-growing and ever-working software ecosystems, those which do make development fun and exciting!</strong> </p>
<p><em>Edit 2019/07/05: Evocate the "hard scarcity of resources" as a possible reason for lack of shims, and tweak the tone of this part.</em></p>
<p><em>Edit 2019/07/14: Fix typos, and warn against in-place semantic changes.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/06/windowsserver_article_012.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
