Most web browsers don’t hide background content when a chat modal (or any modal) opens on a mobile device. When chat pops up, a mask visually filters the background and sighted users see the relevant content and respond. For sight-impaired customers who operate their phones with a built-in screen reader, the mask doesn’t exist. Listening and responding to the unfiltered content creates a noisy and frustrating user experience. 

This noisy problem needed a solution.

Why Listen?

As developers, we use CSS to arrange web pages with complex layouts for visual consumption. CSS helps customers process content in a specific order that we’ve created. In this case, Embedded Chat is not viable for everyone because the background (customer page) and foreground content (chat) are at the same navigation level when using screen readers. This solution brings proper separation so everyone is able to have a focused conversation. Once the window is closed, the full web page content returns.

The phone on the left shows what the screen reader will present when a chat modal opens. The phone on the right shows the experience with the inert attribute added. By adding simple hooks to your code in this Embedded Service Chat example, you create an accessible mobile experience to focus on chatting

Accessibility Matters

“We have the power to build user interfaces that do awesome things, but the flip-side is that sometimes we build interfaces that create barriers.” says Cordelia McGee-Tubb, Principal Accessibility Engineer at Salesforce. “If there’s only one user who has trouble accessing our product and we have a way to improve the experience, we should make that improvement.”

A Solution for Embedded Chat

Our example provides code that will temporarily hide document body children and keep only the Embedded Chat widget accessible and visible to assistive technology. If you would like to try this, make sure you have the Embedded Chat code snippet loaded in a test website and follow the setup steps. Note that this solution is not available for Salesforce Communities.

Start with a base page, our code snippet with an empty onBodyLoaded JavaScript method. The body page content is wrapped with a div with the id #body-content and the body has an onload handler specified. You’ll use the CSS selector #body-content and implement the JavaScript method onBodyLoaded() after adding your snippet.

Base Page Code with Embedded Chat Code Snippet

><html>

<head>

   <meta name=”viewport” content=”width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=0″>

   <script type=’text/javascript’>

        function onBodyLoaded() {

            // You’ll fill in this function during the next step.

        }

   </script>

</head>

<body onload=”onBodyLoaded()”>

   <div id=”body-content”>

       <h1>Welcome to the best website!</h1>

       <style type=’text/css’>

           .embeddedServiceHelpButton .helpButton .uiButton {

               background-color: #A70BA5;

               font-family: “Comic Sans MS”, sans-serif;

           }

           .embeddedServiceHelpButton .helpButton .uiButton:focus {

               outline: 1px solid #A70BA5;

           }

           .previews img {

               max-width: 100%;

               border-radius: 10px;

           }

           .chat-content a {

               color: #fff;

           }

       </style>

   </div>

   <script type=’text/javascript’ src=’https://service.force.com/embeddedservice/5.0/esw.min.js’></script>

   <script type=’text/javascript’>

       var initESW = function (gslbBaseURL) {

           embedded_svc.settings.displayHelpButton = true; //Or false

           embedded_svc.settings.language = ”; //For example, enter ‘en’ or ‘en-US’

           embedded_svc.settings.enabledFeatures = [‘LiveAgent’];

           embedded_svc.settings.entryFeature = ‘LiveAgent’;

           embedded_svc.init(

               // params for your org

           );

       };

       if (!window.embedded_svc) {

           var s = document.createElement(‘script’);

           s.setAttribute(‘src’, ‘https://<yourCoreURL>/embeddedservice/5.0/esw.min.js’);

           s.onload = function () {

               initESW(null);

           };

           document.body.appendChild(s);

       } else {

           initESW(‘https://service.force.com’);

       }

   </script>

</body>

</html>

Next implement the JavaScript method onBodyLoaded to disable the div with id body-content whenever Embedded Chat is opened and re-enable body-content whenever Embedded Chat is minimized/closed. Define the JavaScript method onBodyLoaded in this step. For more help on adding event handlers for maximize, destroy, and minimize, see “Get Chat Event Notifications.”

onBodyLoaded Code

function onBodyLoaded() {

   /**

     * Toggles the inert attribute on background content for the page.

     * The inert attribute needs to be set on parent level DOM

     * nodes. Inert will set the DOM node aria-hidden attribute and

     * and set tab-index=”-1″ on all children so that screen readers

     * can’t access the content.

     */

   function toggleInert(disabled) {

       let bodyElem = document.getElementById(“body-content”);

       if(bodyElem) {

           bodyElem.inert = disabled;

       }

   }

   // Add hooks to toggle inert on our page when Embedded Chat

   // changes state.

   function addA11yHooks() {

       embedded_svc.addEventHandler(‘afterMaximize’, function() {

           toggleInert(true);

       });

       embedded_svc.addEventHandler(‘afterDestroy’, function() {

           toggleInert(false);

       });

       embedded_svc.addEventHandler(‘afterMinimize’, function() {

           toggleInert(false);

       });

   }

   // Early out for desktop.

   if(embedded_svc.isDesktop()) {

       return;

   }

   // Add hooks for mobile.

   addA11yHooks();

}

Download the full combined code for the steps you just completed here from our Github site.

Conclusion

This solution demonstrates that creating an experience for all customers reduces frustration and improves usability. Remember to develop with accessibility in mind so that everyone can use, interact with, and contribute to your applications. To help meet our goal of universal design, salesforce.com follows the internationally recognized best practices in Section 508 of the Rehabilitation Act and the Web Content Accessibility Guidelines (WCAG) 2.0 Level AA to the extent possible. 

To learn more about web accessibility, try this Trail: Get Started with Web Accessibility

Additional resources

Embedded Service for Web Developer Guide 

Salesforce Service Cloud Screen Reader Video

About the author

Susan Rimerman is a Staff Technical Writer for Salesforce Service Cloud. This solution was created by Will Chang, Lead Software Engineer, with help from Cordelia McGee-Tubb, Principal Web Accessibility Engineer.

Get the latest Salesforce Developer blog posts and podcast episodes via Slack or RSS.

Add to Slack Subscribe to RSS