Code Library
JavaScript
Keyboard-Accessible Clickable Modules | Blurb Modules
.et_clickable class (such as Blurbs, Images, or CTAs with link URLs).It adds accessibility and link activation behavior that Divi’s default code doesn’t provide.
What this script does:
- Makes non-anchor modules (
.et_clickable) focusable withtabindex="0". - Adds
role="link"so screen readers announce the module as a link. - Allows keyboard users to activate the link using Enter or Space.
- Uses each module’s built-in
data-hrefattribute for navigation. - Supports opening links in a new tab if
data-target="_blank"ordata-link-target="_blank"is set. - Automatically skips modules that already contain a real
<a>tag to prevent double navigation. - Runs automatically after the page loads and re-applies itself if new modules are added dynamically (in sliders or the Visual Builder).
- Does not apply any visual hover/focus styles — you can control appearance entirely with your own CSS.
How to add this script:
- Site-wide method:
Go to Divi → Theme Options → Integration and paste this entire script into
the “Add code to the <body> (good for tracking codes such as google analytics)” box.
Save changes — it will run automatically on all pages. - Page-specific method:
Add a Code module anywhere on the page (for example, in a footer or header row).
Paste this script inside the Code module and save.
It will only apply to that page. - Important:
Always add this script inside a Code module or Integration field — never in a Text or Toggle module on a live page,
since that would display the code rather than run it.
When to use each version:
- General Script:
Use this version for most projects where your clickable modules are standard Divi Blurbs, CTAs, or Images
that do not contain real<a>tags inside them.
It’s lightweight, simple, and runs site-wide without any customization. - Scoped / Advanced Script:
Use this version when you’re building reusable templates or more complex pages that:- Contain a mix of clickable and non-clickable modules.
- Load modules dynamically (e.g., sliders, AJAX, or Visual Builder updates).
- Need to limit where the keyboard-accessibility applies (for example, only in
.quicklinks-column).
The advanced version is safer for large or shared environments and prevents double-link activation by automatically skipping modules that already include a real anchor (
<a>).
General-Purpose Script (lightweight, site-wide use)
<script>
(function () {
document.querySelectorAll('.et_clickable').forEach(function (el) {
if (!el.hasAttribute('tabindex')) el.setAttribute('tabindex', '0');
if (!el.hasAttribute('role')) el.setAttribute('role', 'link');
var href = el.getAttribute('data-href');
if (href) {
el.addEventListener('keydown', function (e) {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
window.location.href = href;
}
});
}
});
})();
</script>
Scoped / Advanced Script (for dynamic or mixed modules)
<script>
/*
Divi Clickable Modules (Scoped A11y Enabler)
- Adds keyboard access to .et_clickable modules
- Skips any that already contain <a> tags
- Safe for shared templates
*/
(function () {
function upgrade(el) {
if (!el || el.dataset.a11yUpgraded === "1") return;
if (el.querySelector('a[href]')) { el.dataset.a11yUpgraded = "1"; return; }
if (!el.hasAttribute('tabindex')) el.setAttribute('tabindex', '0');
if (!el.hasAttribute('role')) el.setAttribute('role', 'link');
var href = el.getAttribute('data-href');
var newTab = el.getAttribute('data-target') === '_blank';
el.addEventListener('keydown', function (e) {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
if (!href) return;
if (newTab || e.ctrlKey || e.metaKey) {
window.open(href, '_blank', 'noopener');
} else {
window.location.href = href;
}
}
});
el.dataset.a11yUpgraded = "1";
}
function init(root) {
(root || document).querySelectorAll('.et_clickable[data-href]').forEach(upgrade);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function(){ init(document); });
} else {
init(document);
}
var mo = new MutationObserver(function (muts) {
muts.forEach(function (m) {
m.addedNodes && m.addedNodes.forEach(function (n) {
if (n.nodeType === 1) init(n);
});
});
});
mo.observe(document.documentElement, { childList: true, subtree: true });
})();
</script>
Contact List – Adds Aria Label to "Send Message" button
📌 Purpose of This Script
This script adds an accessible aria-label to each “Send message” button generated by the Contact List module. It uses the staff member’s data-name to create text such as:
“Send email to Tyler Ferrara”
This improves screen reader accessibility without changing the visual button.
📍 Where to Add This
Add the script in:
Divi → Theme Options → Integration → “Add code to the <head> of your blog”
Do not add it to the body integration or to a page-level code module.
📝 When This Script Is Used
This script applies automatically when:
The Contact List entry includes an email address
The site is configured to show the Send Message button
The <a> tag includes a data-name attribute (Divi adds this automatically)
No manual HTML editing is required by staff.
🧭 Notes for Content Updaters
When editing Contact List entries:
If an email is added, the secure Send Message button will appear automatically.
This script auto-creates an aria-label with the person’s name.
No manual HTML or attributes are needed.
📄 Full Script (copy & paste)
<script>
document.addEventListener("DOMContentLoaded", function () {
/*
============================================
ACCESSIBLE ARIA-LABELS FOR SEND MESSAGES
----------------------------------------
This script finds all Contact List "Send
message" buttons, reads the staff member's
name from the data-name attribute, and
adds an aria-label that says:
"Send email to (person's name)"
This improves screen reader accessibility
without affecting the visual layout.
============================================
*/
const sendLinks = document.querySelectorAll(
'.contact-list-send-email a[data-name]'
);
sendLinks.forEach(link => {
const personName = link.getAttribute('data-name') || "";
// Build accessible aria-label
const ariaLabel = personName
? `Send email to ${personName}`
: "Send email";
link.setAttribute("aria-label", ariaLabel);
});
});
</script>
Contact List – Replace Email with "Send Message" (Special Case)
Brief Explanation
This is a non-standard, special-case configuration and should only be offered as an option when specifically requested by the client.
This version is used only in situations where the client does not want to use Divi’s secure “Send Message” button, but also does not want the staff member’s email address visible on the page.
Instead, the script:
- Converts the visible email address into the text “Send Message”
- Opens the mailto link in a new browser tab
- Adds an accessibility-friendly ARIA label with the staff member’s name
📌 Contact List Settings Required for This Script
This script is intended only for the configuration where the **built-in Send Message button is hidden** and the **contact email address is visible**.
Please verify the following settings inside the Contact List plugin before using the script:
1️⃣ Hide the built-in Send Message button
- Go to: WordPress Dashboard → Contact List → Settings
- Select the General Settings tab
- Scroll to the bottom and check the option:
✔ “Hide Send Message – button from the public list”
2️⃣ Ensure the email address is visible
- In the same Settings panel, select the reCAPTCHA and Email tab
- At the top of that tab, uncheck:
✖ “Hide contact email address from contact card”
Once both conditions are met, the email link will remain visible and the script will:
- Replace the visible email address text with “Send Message”
- Add an accessibility-focused ARIA label including the contact’s name
- Open the mailto link in a new tab
📍 Where to Add This Script in Divi
- Go to Dashboard → Divi → Theme Options
- Click the Integration tab
- Find the field labeled: “Add code to the <head> of your blog”
- Save changes, then clear any caching if applicable (Divi cache, server cache, and browser cache)
📄 Full Script (copy & paste)
<script>
/**
* Contact List – Email Link Accessibility Helper
*
* What this script does:
* - Finds each ".contact-list-main-elements" block.
* - Reads the visible full name from ".contact-list-contact-name".
* - Adds an aria-label such as "Send message to Tricia Rummel" to the email link.
* - Replaces the visible email address with "Send Message".
* - Adds: target="_blank" and rel="noopener noreferrer" for safe new-tab behavior.
*/
document.addEventListener('DOMContentLoaded', function () {
const items = document.querySelectorAll('.contact-list-main-elements');
items.forEach(item => {
const nameElem = item.querySelector('.contact-list-contact-name');
const emailElem = item.querySelector('.contact-list-email a');
if (nameElem && emailElem) {
const fullName = nameElem.textContent.trim();
const ariaLabel = `Send message to ${fullName}`;
// Add ARIA label for accessibility
emailElem.setAttribute('aria-label', ariaLabel);
// Replace link text
emailElem.textContent = 'Send Message';
// Open in new tab safely
emailElem.setAttribute('target', '_blank');
emailElem.setAttribute('rel', 'noopener noreferrer');
}
});
});
</script>
Sidebar – Hide the sidebar at mobile/tablet when empty
Brief Explanation
The sidebar can sometimes create unwanted space at mobile/tablet even though there is no content. This script will set it to display:none; if it is empty.
📍 Where to Add This Script in Divi
- Go to Dashboard → Divi → Theme Options
- Click the Integration tab
- Find the field labeled: “Add code to the <head> of your blog”
- Paste the JavaScript into the section
- Save changes, then clear any caching if applicable (Divi cache, server cache, and browser cache)
📄 Full Script (copy & paste)
<script>
/**
* Hide Empty Sidebar Column on Mobile Devices
*
* Purpose: Automatically hides sidebar columns that have no content when viewed
* on mobile/tablet devices (screens 980px wide or less). This prevents empty
* whitespace from appearing in the layout on smaller screens.
*
* How it works:
* - Targets columns with the "sidebar-content" class
* - Checks if the column is empty using multiple detection methods
* - Hides empty columns on screens ≤ 980px
* - Shows columns again on larger screens (> 980px)
* - Runs on page load, window resize, and after content loads
*
* Compatible with: Divi theme and WordPress
*/
jQuery(document).ready(function($) {
function handleSidebarColumnVisibility() {
if (window.innerWidth <= 980) {
$('.et_pb_column.sidebar-content').each(function() {
var $column = $(this);
var isEmpty = false;
if ($column.html().trim() === '') {
isEmpty = true;
} else if ($column.children().length === 0) {
isEmpty = true;
} else if ($column.children(':visible').length === 0) {
isEmpty = true;
} else if ($column.text().trim() === '') {
isEmpty = true;
}
if (isEmpty) {
$column.hide();
} else {
$column.show();
}
});
} else {
$('.et_pb_column.sidebar-content').show();
}
}
handleSidebarColumnVisibility();
var resizeTimer;
$(window).on('resize', function() {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(handleSidebarColumnVisibility, 250);
});
$(window).on('load', function() {
setTimeout(handleSidebarColumnVisibility, 100);
});
});
</script>HTML
Embedding a Facebook Feed
This example provides a skip link for screen readers and a placeholder for adding a Facebook Page Plugin feed.
Instructions for generating the Facebook Feed code:
- Go to the official Facebook Page Plugin generator:
https://developers.facebook.com/docs/plugins/page-plugin - In the Facebook Page URL field, enter the full address of your Facebook page (for example:
https://www.facebook.com/YourPageName).
This becomes thehrefinside the embed code. - Leave the Tabs field as
timeline(this shows your timeline feed). - Select your desired Width and Height values.
These determine how wide and tall the feed will appear on your page. - In the four options below the generator:
- Check ✅
small_header - Check ✅
adapt_container_width - Uncheck 🚫
hide_cover - Uncheck 🚫
show_facepile
- Check ✅
- Click the “Get Code” button.
- In the popup, click the “Iframe” tab to switch from JavaScript to the simpler iframe version.
- Copy the entire
<iframe>...</iframe>code that Facebook generates. - Paste that iframe code into the spot indicated below (where it says <!– <iframe> goes here –>).
Example HTML structure
<!-- facebook feed -->
<div class="skip">
<a href="#skipFacebook" role="link" class="">Skip Facebook Feed</a>
</div>
<!-- <iframe> goes here -->
<div id="skipFacebook" tabindex="-1"></div>
Accessibility note:
The skip link allows keyboard and screen reader users to bypass the Facebook embed and return to the rest of the page content.
The final div with id="skipFacebook" serves as the destination for that skip link.
CSS
DP Blog Slider – Pagination Dots (CSS)
This CSS customizes the pagination dots (bullets) used in the DP Blog Slider.
It enhances the appearance, hover and focus states, and accessibility of the slider’s pagination controls.
Instructions:
- Add this CSS to your site using one of these methods:
- Site-wide: Go to Divi → Theme Options → Custom CSS and paste it there.
- Page-specific: In the page builder, open Page Settings → Advanced → Custom CSS and paste the code.
- Module-level: Add a Code module and paste the CSS inside.
- Replace
.YOUR_CLASS_NAMEwith the actual class used on your slider (for example,.sequoia-news). - No JavaScript is required — this is pure CSS.
Example CSS:
/* === Pagination bullet base styles === */
.YOUR_CLASS_NAME .swiper-pagination-bullet {
background-color: #fff !important;
border: 2px solid var(--primary-color) !important;
opacity: 1 !important; /* override Swiper dimming */
min-width: 16px;
min-height: 16px;
margin: 0 6px !important;
border-radius: 50% !important;
transition: background-color .3s ease, transform .3s ease, border-color .3s ease;
cursor: pointer;
}
/* === Active bullet appearance === */
.YOUR_CLASS_NAME .swiper-pagination-bullet.swiper-pagination-bullet-active {
background-color: var(--primary-color) !important;
border-color: var(--primary-color) !important;
transform: scale(1.1);
}
/* === Hover and focus interaction states === */
.YOUR_CLASS_NAME .swiper-pagination-bullet:hover,
.YOUR_CLASS_NAME .swiper-pagination-bullet:focus {
outline: 2px solid var(--primary-color) !important;
outline-offset: 2px !important;
transform: scale(1.15);
background-color: var(--primary-color) !important;
border-color: var(--primary-color) !important;
color: #fff !important;
}
/* === Visible keyboard focus ring (focus-visible only) === */
.YOUR_CLASS_NAME .swiper-pagination-bullet:focus-visible {
outline: 2px solid var(--primary-color) !important;
outline-offset: 2px !important;
}
/* === Hide pagination when only one bullet exists === */
.YOUR_CLASS_NAME .swiper-pagination { display: none !important; }
.YOUR_CLASS_NAME .swiper-pagination:has(.swiper-pagination-bullet:nth-child(2)) { display: block !important; }
Adding an Icon to the Parent of a Button
This CSS adds FontAwesome icons (e.g., Facebook, Instagram, calendar) to the parent wrapper of Divi buttons. Because it targets the ::after pseudo-element of the button’s parent, it does not interfere with your normal ::before or ::after hover effects on the button itself.
Instructions:
- Add this CSS to your site using one of these methods:
- Site-wide: Divi → Theme Options → Custom CSS.
- Page-specific: Page Settings → Advanced → Custom CSS.
- Module-level: Inside a Code module within your layout.
- In the Button Module settings, click on the Advanced tab → open the CSS ID & Classes toggle → and enter your chosen class name (for example,
facebook-button) in the CSS Class field. - Update the same class name inside the CSS selectors that use
:has().
For example, if your button’s CSS class isinstagram-button, change both selectors to use:.et_pb_button_module_wrapper:has(.instagram-button) - The icon uses FontAwesome. Update the
contentvalue to match the desired icon:'\f39e'= Facebook “f”'\f16d'= Instagram'\e61b'= X (formerly Twitter)'\f073'= Calendar
- This approach keeps the icon independent from the button’s hover animations and transitions, so your existing effects still work normally.
Example CSS:
/****** ADDING an ICON on the PARENT of a button ******/
/* Targets the parent for buttons with the class of "facebook-button" */
.et_pb_button_module_wrapper:has(.facebook-button)::after {
content: '\f39e'; /* Facebook "f" */
position: absolute;
left: 10px;
top: 50%; /* first half of vertical centering */
-webkit-transform: translateY(-50%);
-moz-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%); /* second half of vertical centering */
z-index: 10;
font-family: 'FontAwesome';
font-size: 40px;
font-weight: 400;
color: var(--primary-color);
-webkit-transition: all 0.3s ease;
-moz-transition: all 0.3s ease;
-o-transition: all 0.3s ease;
transition: all 0.3s ease;
pointer-events: none; /* Prevents the icon pseudo-element from blocking mouse events,
allowing hover and click interactions to pass through to the button underneath */
}
/* Adds hover/focus styling to the parent of buttons with the class "facebook-button" */
.et_pb_button_module_wrapper:has(.facebook-button:hover)::after,
.et_pb_button_module_wrapper:has(.facebook-button:focus)::after {
color: #fff;
font-size: 30px;
}
Contact List - CSS for the contact list
Brief Explanation
This is the custom CSS for styling the Contact List plugin in Divi.
The Send Message, Biography, and Custom URLs are styled as underlined text instead of as buttons.
The image styles are located at the bottom for easy customization across different templates.
📍 Where to Add This CSS in Divi
- Go to Dashboard → Divi → Theme Options
- Click the General tab
- Scroll down to “Custom CSS”
- Paste the CSS into the section
- Save changes
📄 Full CSS (copy & paste)
/***** CONTACT LIST STYLES *****/
/******** LAYOUT & STRUCTURE ********/
.contact-list-main-elements {
display: flex;
flex-direction: column;
}
/* Hide empty elements so that they don't create extra space */
.contact-list-main-elements > :empty {
display: none;
}
div#main-content, .et_builder_inner_content, .et_pb_column_inner {
z-index: auto;
}
/* Contact List Layout */
ul#all-contacts {
display: flex;
flex-wrap: wrap;
}
.sidebar-contacts ul#all-contacts {
flex-direction: column; /* already inherits flex + wrap from ul#all-contacts */
}
.sidebar-contacts ul#all-contacts li {
width: 100%;
}
.contact-list-contact-container {
flex-direction: column;
}
.contact-list-main-left {
order: 2;
}
/* Contact List Container Resets */
#all-contacts li .contact-list-contact-container {
height: auto !important;
padding: 0 !important;
border-radius: 0 !important;
}
/******** MODAL / FLYOUT STYLES ********/
.cl-modal-container .cl-modal {
min-width: auto;
max-width: 630px;
}
/* SEND MESSAGE FLYOUT: h3 header */
.cl-modal-container.cl-modal-container-send-message h3 {
color: white;
background: var(--primary-color);
padding-left: 22px;
margin: 20px -24px;
padding-top: 7px;
}
/* SEND MESSAGE FLYOUT: submit button */
.cl-modal-container.cl-modal-container-send-message input.contact-list-send-single-submit {
background: var(--primary-color);
color: #fff;
-webkit-transition: .2s linear;
-o-transition: .2s linear;
transition: .2s linear;
}
/* Send Message submit button HOVER */
.cl-modal-container.cl-modal-container-send-message input.contact-list-send-single-submit:hover,
.cl-modal-container.cl-modal-container-send-message input.contact-list-send-single-submit:focus {
background: var(--primary-color);
color: #fff;
outline: 3px solid var(--primary-color);
outline-offset: 5px;
}
/* Send Message input fields */
.cl-modal-container.cl-modal-container-send-message label,
.cl-modal-container.cl-modal-container-send-message input {
font-size: 1rem !important; /* ADA */
}
/* BIOGRAPHY FLYOUT */
.contact-list-description {
padding-bottom: 15px;
}
/******** CONTACT NAME ********/
/* Contact Name in Search Results */
#contact-list-search ul li .contact-list-contact-name {
font-size: 1.1rem !important;
}
/******** EMAIL / SEND MESSAGE LINK ********/
/* Email Button (Send Message) */
span.contact-list-send-email {
padding: 0;
border-radius: 0 !important;
}
span.contact-list-send-email a {
border: 0;
border-radius: 0 !important;
padding: 0 !important;
text-transform: none;
font-weight: 400;
font-size: 1rem;
text-decoration: underline !important;
color: var(--primary-color) !important;
margin: 0;
width: 10rem;
}
/* Email Button (When shown with border style) */
.contact-list-send-email a {
padding: 0 7px !important;
}
/* Email Link Hover */
.contact-list-send-email a:not(.bogus-class):hover {
text-decoration: none;
background: transparent !important;
color: var(--primary-color) !important;
border: 0;
}
/* Email Link Focus */
.contact-list-send-email a:not(.bogus-class):focus {
outline: 1px solid;
outline-offset: -2px !important;
}
/* Email as plain text */
#contact-list-search .contact-list-email {
font-size: 16px;
word-break: break-all;
}
#contact-list-search .contact-list-email a {
font-size: 1rem;
color: var(--primary-color);
word-break: break-all;
}
/******** BIOGRAPHY LINK ********/
/* Biography Link (Inline text) */
a.contact-list-show-contact {
border: 0;
margin: 0;
padding: 0;
text-transform: none;
font-weight: 400;
font-size: 1rem;
text-decoration: underline !important;
color: var(--primary-color);
}
/* Biography Button - styled as link */
a.contact-list-show-contact-button {
border: 0;
border-radius: 0 !important;
padding: 0 !important;
text-transform: none;
font-weight: 400;
font-size: 1rem;
text-decoration: underline !important;
color: var(--primary-color) !important;
margin: 0;
width: 10rem;
}
/* Biography Button Hover */
.contact-list-show-contact-button:not(.bogus-class):hover {
text-decoration: none !important;
background: transparent !important;
color: var(--primary-color) !important;
border: 0;
}
/* Biography Button Focus */
.contact-list-show-contact-button:not(.bogus-class):focus {
text-decoration: none !important;
background: transparent !important;
color: var(--primary-color) !important;
border: 0;
outline: 1px solid;
outline-offset: -2px !important;
}
/******** CUSTOM URL LINKS (Teacher Website, etc.) ********/
/* Custom URL Container */
.contact-list-custom-urls-container {
margin-top: 3px !important;
}
.contact-list-custom-urls-container a {
margin-bottom: 2px !important;
}
/* Hide empty "Teacher Website" link */
.contact-list-custom-urls-container a[href=""] {
display: none;
}
/* Custom URL Links - styled as links */
.contact-list-card-custom-url-1,
.contact-list-card-custom-url-2 {
border: 0;
margin: 0;
padding: 0 !important;
text-transform: none;
font-weight: 400;
font-size: 1rem;
text-decoration: underline !important;
color: var(--primary-color) !important;
}
/* Custom URL Hover */
.contact-list-card-custom-url-1:hover,
.contact-list-card-custom-url-2:hover {
text-decoration: none !important;
background: transparent !important;
color: var(--primary-color) !important;
border: 0;
}
/* Custom URL Focus */
.contact-list-card-custom-url-1:focus,
.contact-list-card-custom-url-2:focus {
text-decoration: none !important;
background: transparent !important;
color: var(--primary-color) !important;
border: 0;
outline: 1px solid;
outline-offset: -2px !important;
}
/******** PHONE NUMBER ********/
span.contact-list-phone a:focus {
outline: 1px solid;
outline-offset: 0px !important;
}
/******** SEARCH ********/
/* Search Spacing */
#contact-list-search {
margin-bottom: 0 !important;
}
#contact-list-search ul li {
margin: 0 !important;
}
/******** RESPONSIVE ADJUSTMENTS ********/
@media (max-width: 820px) {
.contact-list-2-cards-on-the-same-row #all-contacts li,
.contact-list-3-cards-on-the-same-row #all-contacts li {
float: none;
width: 50%;
}
a.contact-list-show-contact-button {
margin-bottom: 20px;
}
}
@media (max-width: 499px) {
ul#all-contacts {
flex-direction: column;
}
.contact-list-2-cards-on-the-same-row #all-contacts li,
.contact-list-3-cards-on-the-same-row #all-contacts li {
width: 100%;
}
}
/******** IMAGE STYLES (Customize for different templates) ********/
.contact-list-main-right {
width: 150px !important; /* Determines image width */
}
.contact-list-image img {
border: 10px solid var(--primary-color);
outline: 5px solid #fff;
outline-offset: -10px;
}
Shortcodes
Contact Manager Shortcode
This shortcode is used to display a contact list from the Contact Manager plugin. Add it to a Code module on the target page. Change the group value as needed.
Instructions:
- Add a Code module where you want the list to appear.
- Paste the shortcode and update the
groupname (e.g.,administration).
Example Shortcode (copy this):
/* Contact Manager code */
[contact_list show_filters=0 hide_search=1 group=administration]
Tip: Alternatively, you can write it with double brackets in docs so WordPress won’t parse it:
[contact_list show_filters=0 hide_search=1 group=administration]. When someone copies it, they just remove one bracket from each side.