How to Build a Dynamically Positioned Popover with Popper.js and Divi

Feb 23, 2021 | Everything Divi for WordPress

The popper.js library is a powerful positioning engine for tooltips and popovers. Today, we are honing in on how to make a popover. You can think of a popover as a tooltip that can contain more content. What makes Popper so effective is its ability to generate popovers that maintain an optimal position on the page when its location or the browser viewport changes. This can be a simple and effective UX and UI solution for web developers. That’s probably why it is integrated with other popular libraries like Boostrap and Material UI.

In this tutorial, we are going to harness the power of Popper.js in Divi to create a dynamically positioned popover when clicking a button. This will allow anyone to create a popover using Divi elements to display any content they want when clicking a button.  Plus, the popover content will automatically adjust its position to preserve the most ideal visibility as the user interacts with your page.

Here is an illustration of the positioning of these popovers…

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi How to Build a Dynamically Positioned Popover with Popper.js and Divi

To accomplish this, we are going to rely on some custom CSS and Javascript for the functionality. But we can still rely on the powerful design capabilities of the Divi Builder to create a Popper-powered popover using any Divi element. And the example we are going to build in this tutorial is a popover menu.

Let’s get started!

Sneak Peek

Here is a quick look at the example popover menu we will design in this tutorial.

Notice how the position of the popover changes dynamically as the user scrolls or changes the browser size.

If you click the button while it is at the very top of the browser viewport, the popover will be displayed below the button, and if you click the button while it is at the very bottom of the viewport, the popover will be displayed above the button. And if the popover is originally positioned to the right of the button on large viewports, it will flip to a top or bottom position on smaller viewports.

Also don’t miss the little arrow that is also positioned to dynamically point to its reference (or in this case, the button).


Download the Layout for FREE

To lay your hands on the popover example layout from this tutorial, you will first need to download it using the button below. To gain access to the download you will need to subscribe to our Divi Daily email list by using the form below. As a new subscriber, you will receive even more Divi goodness and a free Divi Layout pack every Monday! If you’re already on the list, simply enter your email address below and click download. You will not be “resubscribed” or receive extra emails.

You have successfully subscribed. Please check your email address to confirm your subscription and get access to free weekly Divi layout packs!

To import the section layout to your Divi Library, navigate to the Divi Library.

Click the Import button.

In the portability popup, select the import tab and choose the download file from your computer.

Then click the import button.

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-1 How to Build a Dynamically Positioned Popover with Popper.js and Divi

Once done, the section layout will be available in the Divi Builder.

Let’s get to the tutorial, shall we?

What You Need to Get Started

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-2 How to Build a Dynamically Positioned Popover with Popper.js and Divi

To get started, you will need to do the following:

  1. If you haven’t yet, install and activate the Divi Theme.
  2. Create a new page in WordPress and use the Divi Builder to edit the page on the front end (visual builder).
  3. Choose the option “Build From Scratch”.

After that, you will have a blank canvas to start designing in Divi.

Creating a Popover with Popper.js and Divi

As previously mentioned, we are going to use popper.js in Divi to create a dynamically positioned popover (the pop-up box) that is revealed when clicking on the popover’s reference (the button).  With Divi, we can build these two (the pop-up box and the button) using the Divi builder. Then later we are going to add the code necessary to marry the two in perfect position harmony.

we are going to designate a row as the popper (the thing that popups up when clicking the button). Then we can add modules to the row to include the content we want to show in the popper popover. In this example

The Section

To begin, let’s go ahead and add a custom CSS ID to the regular section that is ready by default. Open the section settings and add the following ID:

  • CSS ID: popper-section

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-3 How to Build a Dynamically Positioned Popover with Popper.js and Divi

Create Popper Popover with Divi Row

Next, add a one-column row to the section. This row will become our Popper popover element that pops up when clicking a button.

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-4 How to Build a Dynamically Positioned Popover with Popper.js and Divi

Open the row settings and update the styling as follows:

  • Background Color: #333333

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-5 How to Build a Dynamically Positioned Popover with Popper.js and Divi

  • Gutter Width: 2
  • Width: 100%
  • Max Width: 500px
  • Padding: 0px top, 0px bottom, 0px left, 0px right
  • Rounded Corners: 10px

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-6 How to Build a Dynamically Positioned Popover with Popper.js and Divi

Because this row will become our popper popover element, we need to add a CSS ID to serve as a selector in our code. We also need to make sure the visibility remains on overflow (it is hidden by the rounded corners).

Go to the advanced tab and update the following:

  • CSS ID: popper-popup
  • Horizontal Overflow: visible
  • Vertical Overflow: visible

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-7 How to Build a Dynamically Positioned Popover with Popper.js and Divi

Add Content to Popover Row

Here is where the power of Divi shines. We can add any module(s) we want to our row to fill the popover with whatever content we want using the Divi Builder to design them. For this example, we are going to add some buttons to the row to serve as a custom menu that appears within the popover.

To start, add a button module to the column of the row.

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-8 How to Build a Dynamically Positioned Popover with Popper.js and Divi

Now let’s add some styling to our button real quick. Update the button settings as follows:

  • Button Alignment: center
  • Use Custom Styles for Button: YES
  • Button Border Width: 1px
  • Button Border Color: #555555
  • Button Border Radius: 10px
  • Button Icon: see screenshot
  • Margin: 20px top, 20px bottom, 20px left, 20px right
  • Padding: 0.5em top, 0.5em bottom, 2em left, 2em right

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-9 How to Build a Dynamically Positioned Popover with Popper.js and Divi

NOTE: We need to use margin on the modules to create spacing instead of relying on row (or column) padding because we will be adding an arrow (using a divider) that needs to be positioned on the edge of the row (with absolute position). Any row or column padding will push the arrow away from the edge.

Next, add the following custom CSS snippet to the Main Element to make the button span the full width of the column/row:

display: block !important

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-10 How to Build a Dynamically Positioned Popover with Popper.js and Divi

Now duplicate the button two (or more) times to add a few more buttons to our menu popover.

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-11 How to Build a Dynamically Positioned Popover with Popper.js and Divi

Creating the Popover Arrow

Popper.js has built-in support for positioning an arrow along with the popover. To build the arrow, add a new divider under the last button in our row.

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-12 How to Build a Dynamically Positioned Popover with Popper.js and Divi

In the divider settings, select not to show the divider.

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-13 How to Build a Dynamically Positioned Popover with Popper.js and Divi

Then, under the advanced tab, add the following CSS ID:

  • CSS ID: popper-arrow

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-14 How to Build a Dynamically Positioned Popover with Popper.js and Divi

We’ll be using custom external CSS to style and position the arrow later.

Creating the Popover Button (or Reference)

The two key elements of a popper popover include the popover element (or popper) and the reference that the popover attaches itself to. You can use any Divi element as a reference that generates the popover, but for this example, we are going to use a button.

Create Popper Reference Button

Before we create our button, we need to add a new one-column row under our popover row.

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-15 How to Build a Dynamically Positioned Popover with Popper.js and Divi

Then add a new button module to the row.

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-16 How to Build a Dynamically Positioned Popover with Popper.js and Divi

Update the button settings with some basic styling as follows:

  • Button Text Color: #ffffff
  • Button Background Color: #a043e8
  • Button Border Width: 0px
  • Button Border Radius: 10px

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-17 How to Build a Dynamically Positioned Popover with Popper.js and Divi

Next, add the necessary CSS ID that will allow us to target and use the button as our popover reference later:

  • CSS ID: popper-button

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-18 How to Build a Dynamically Positioned Popover with Popper.js and Divi

The Code

Now that our popover and button are complete, we are ready to add the code to make the magic happen.

To do this, add a code module under the reference button module in the second row.

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-19 How to Build a Dynamically Positioned Popover with Popper.js and Divi

It is important that the code is at the bottom of the page for it to work.

First, we’ll add the CSS.

In the code content box, add the style tags that are needed to wrap CSS in HTML. Then copy and paste the following CSS between the style tags:

/*hide and show popup styling*/ #popper-popup { display: none;
}
#popper-popup[data-popper-reference-hidden] { visibility: hidden; pointer-events: none;
}
#popper-popup[show-popper] { display: block; z-index: 9999;
} /*keep popper visible in the Divi Builder for editing*/ #et-fb-app #popper-popup { display: block;
} /*build the arrow targeting the divider with class 'popper-arrow'*/ #popper-arrow,
#popper-arrow::before { position: absolute; width: 8px; height: 8px; background: #333333;
}
#popper-arrow { visibility: hidden;
}
#popper-arrow::before { visibility: visible; content: ""; transform: rotate(45deg);
} /*position arrow using popper.js data-popper-placement attribute*/ #popper-popup[data-popper-placement^="top"] #popper-arrow { bottom: -4px;
} #popper-popup[data-popper-placement^="bottom"] #popper-arrow { top: -4px;
} #popper-popup[data-popper-placement^="left"] #popper-arrow { right: -4px;
} #popper-popup[data-popper-placement^="right"] #popper-arrow { left: -4px;
} /*hide arrow when reference outside of viewport*/
#popper-popup[data-popper-reference-hidden] #popper-arrow::before { visibility: hidden;
}

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-20 How to Build a Dynamically Positioned Popover with Popper.js and Divi

Next, we need to access the popper.js library by adding a script that imports Popper.js from their CDN (https://unpkg.com/@popperjs/[email protected]). Under the ending style tag, paste the following script in the code box.

Use the following src within a script tag to import the library:

src="https://unpkg.com/@popperjs/[email protected]"

It should look like this:

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-21 How to Build a Dynamically Positioned Popover with Popper.js and Divi

It is important to import Popper.js before adding the code that will use it. So, after the script pointing to Popper.js, add the necessary script tags to wrap the Javascript we need to add. Then paste the following Javascript in between the script tags.

const popperButton = document.querySelector("#popper-button");
const popperPopup = document.querySelector("#popper-popup");
const popperSection = document.querySelector("#popper-section");
const popperArrow = document.querySelector("#popper-arrow"); let popperInstance = null; //create popper instance
function createInstance() { popperInstance = Popper.createPopper(popperButton, popperPopup, { placement: "auto",//preferred placement of popper modifiers: [ { name: "offset",//offsets popper from the reference/button options: { offset: [0, 8], }, }, { name: "flip",//flips popper with allowed placements options: { allowedAutoPlacements: ["right", "left", "top", "bottom"], rootBoundary: "viewport", }, }, ], });
} //destroy popper instance
function destroyInstance() { if (popperInstance) { popperInstance.destroy(); popperInstance = null; }
} //show and create popper
function showPopper() { popperPopup.setAttribute("show-popper", ""); popperArrow.setAttribute("data-popper-arrow", ""); createInstance();
} //hide and destroy popper instance
function hidePopper() { popperPopup.removeAttribute("show-popper"); popperArrow.removeAttribute("data-popper-arrow"); destroyInstance();
} //toggle show-popper attribute on popper to hide or show it with CSS function togglePopper() { if (popperPopup.hasAttribute("show-popper")) { hidePopper(); } else { showPopper(); }
}
//execute togglePopper function when clicking the popper reference/button
popperButton.addEventListener("click", function (e) { e.preventDefault(); togglePopper();
});

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-22 How to Build a Dynamically Positioned Popover with Popper.js and Divi

That’s it! We are all done. But before we check out the final result, let’s take a closer look at the code being used.

About the Code

The inspiration for this tutorial came from the Popper tutorial that shows you how to get a basic popup up and running. All I did was tweak the code to generate a popover on click and then used selectors to target Divi elements. Other than the unique constructor createPopper which creates the popper instance and the modifiers (like offset, and flip) used to control the popover positioning logic, the code is all basic Javascript.

If you are interested in how this code works, here is a quick overview.

The Javascript

First, you must import popper.js with their CDN.

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-21 How to Build a Dynamically Positioned Popover with Popper.js and Divi

Then, we need to add some variables that will be used to target 4 key selectors including the popper popover element (#popper-popup), the popper reference/button (#popper-button), the popper arrow that points to the reference/button (#popper-arrow), and the popper popover boundary to keep the popover from overflowing outside the viewport as long as possible (#popper-section).

const popperButton = document.querySelector("#popper-button");
const popperPopup = document.querySelector("#popper-popup");
const popperSection = document.querySelector("#popper-section");
const popperArrow = document.querySelector("#popper-arrow");

Next, we let the variable popperInstance = null to help keep the popperInstance from running until we need it.

let popperInstance = null;

Next, we create a Popper instance which will basically create the popper popover using a few modifiers that control how the popover will adjust its placement on the page.

//create popper instance
function createInstance() { popperInstance = Popper.createPopper(popperButton, popperPopup, { placement: "auto",//preferred placement of popper modifiers: [ { name: "offset",//offsets popper from the reference/button options: { offset: [0, 8], }, }, { name: "flip",//flips popper with allowed placements options: { allowedAutoPlacements: ["right", "left", "top", "bottom"], rootBoundary: "viewport", }, }, ], });
}

Next, we create 4 functions to destroy the popper instance when not active, show the popper when active, hide the popper when not active, and toggle the show or hide functions when popper has the attribute show-popper.

//destroy popper instance
function destroyInstance() { if (popperInstance) { popperInstance.destroy(); popperInstance = null; }
} //show and create popper
function showPopper() { popperPopup.setAttribute("show-popper", ""); popperArrow.setAttribute("data-popper-arrow", ""); createInstance();
} //hide and destroy popper instance
function hidePopper() { popperPopup.removeAttribute("show-popper"); popperArrow.removeAttribute("data-popper-arrow"); destroyInstance();
} //toggle show-popper attribute on popper to hide or show it with CSS function togglePopper() { if (popperPopup.hasAttribute("show-popper")) { hidePopper(); } else { showPopper(); }
}

Finally, we toggle the execution of the popper on click by running the togglePopper() function when clicking the reference/button.

//execute togglePopper function when clicking the popper reference/button
popperButton.addEventListener("click", function (e) { e.preventDefault(); togglePopper();
});

The CSS

The popover functionality relies on some custom CSS to style the selectors we used in the Javascript.

The most essential CSS needed for the popover includes the snippets that hide and show the popper.

/*hide and show popup styling*/ #popper-popup { display: none;
}
#popper-popup[data-popper-reference-hidden] { visibility: hidden; pointer-events: none;
}
#popper-popup[show-popper] { display: block; z-index: 9999;
}

After that, the rest of the CSS is used to style and position the small popup arrow.

Here is the CSS that builds the arrow out of the Divi Divider.

/*build the arrow targeting the divider with class 'popper-arrow'*/ #popper-arrow,
#popper-arrow::before { position: absolute; width: 8px; height: 8px; background: #333333;
}
#popper-arrow { visibility: hidden;
}
#popper-arrow::before { visibility: visible; content: ""; transform: rotate(45deg);
} 

And here is the CSS that uses Popper’s built in data-popper-placement attribute to customize the position of the arrow at all four possible positions and then hides the arrow using the data-popper-reference-hidden attribute.

/*position arrow using popper.js data-popper-placement attribute*/ #popper-popup[data-popper-placement^="top"] #popper-arrow { bottom: -4px;
} #popper-popup[data-popper-placement^="bottom"] #popper-arrow { top: -4px;
} #popper-popup[data-popper-placement^="left"] #popper-arrow { right: -4px;
} #popper-popup[data-popper-placement^="right"] #popper-arrow { left: -4px;
} /*hide arrow when reference out of viewport*/
#popper-popup[data-popper-reference-hidden] #popper-arrow::before { visibility: hidden;
} 

Final CSS and JS

And here is another look at the final CSS and JS code:

/*hide and show popup styling*/ #popper-popup { display: none;
}
#popper-popup[data-popper-reference-hidden] { visibility: hidden; pointer-events: none;
}
#popper-popup[show-popper] { display: block; z-index: 9999;
} /*keep popper visible in the Divi Builder for editing*/ #et-fb-app #popper-popup { display: block;
} /*build the arrow targeting the divider with class 'popper-arrow'*/ #popper-arrow,
#popper-arrow::before { position: absolute; width: 8px; height: 8px; background: #333333;
}
#popper-arrow { visibility: hidden;
}
#popper-arrow::before { visibility: visible; content: ""; transform: rotate(45deg);
} /*position arrow using popper.js data-popper-placement attribute*/ #popper-popup[data-popper-placement^="top"] #popper-arrow { bottom: -4px;
} #popper-popup[data-popper-placement^="bottom"] #popper-arrow { top: -4px;
} #popper-popup[data-popper-placement^="left"] #popper-arrow { right: -4px;
} #popper-popup[data-popper-placement^="right"] #popper-arrow { left: -4px;
} /*hide arrow when reference outside of viewport*/
#popper-popup[data-popper-reference-hidden] #popper-arrow::before { visibility: hidden;
}
const popperButton = document.querySelector("#popper-button");
const popperPopup = document.querySelector("#popper-popup");
const popperSection = document.querySelector("#popper-section");
const popperArrow = document.querySelector("#popper-arrow"); let popperInstance = null; //create popper instance
function createInstance() { popperInstance = Popper.createPopper(popperButton, popperPopup, { placement: "auto",//preferred placement of popper modifiers: [ { name: "offset",//offsets popper from the reference/button options: { offset: [0, 8], }, }, { name: "flip",//flips popper with allowed placements options: { allowedAutoPlacements: ["right", "left", "top", "bottom"], rootBoundary: "viewport", }, }, ], });
} //destroy popper instance
function destroyInstance() { if (popperInstance) { popperInstance.destroy(); popperInstance = null; }
} //show and create popper
function showPopper() { popperPopup.setAttribute("show-popper", ""); popperArrow.setAttribute("data-popper-arrow", ""); createInstance();
} //hide and destroy popper instance
function hidePopper() { popperPopup.removeAttribute("show-popper"); popperArrow.removeAttribute("data-popper-arrow"); destroyInstance();
} //toggle show-popper attribute on popper to hide or show it with CSS function togglePopper() { if (popperPopup.hasAttribute("show-popper")) { hidePopper(); } else { showPopper(); }
}
//execute togglePopper function when clicking the popper reference/button
popperButton.addEventListener("click", function (e) { e.preventDefault(); togglePopper();
});

Viewing the Final Result

To view the result of this example, we need to create some scrolling space to test out the positioning magic of the popper popover.

To do this, open the section settings and add some margin as follows:

  • Margin: 80vh top, 80vh bottom

how-to-build-a-dynamically-positioned-popover-with-popper-js-and-divi-23 How to Build a Dynamically Positioned Popover with Popper.js and Divi

Here is what the functionality looks like on a larger desktop viewport.

Here is what the functionality looks like when adjusting the browser width.

Notice how the position of the popover (and arrow) changes dynamically as the user scrolls or changes the browser size.

Final Thoughts

Creating a popper.js popover in Divi does rely on a good bit of Javascript, but the result is worth it. The dynamic positioning of the popover is such a great UI component that would benefit any website. Hopefully, this will come in handy for any of your popover needs in Divi going forward.

I look forward to hearing from you in the comments.

Cheers!


Source

WordPress Development

SEO NEWS

seo news

We’re listening.

Have something to say about this article? Share it with us on Facebook, Twitter or LinkedIn:

SHARE IT HERE:

Subscribe ToThe Weekly SEO Trade News Updates

Get the latest SEO, SEM and SMM marketing intel, tips and tricks from one of the best SEO Gurus online. 

Every Tuesday morning we send out an aggregated email listing all new posts on SEO Trade News.

Excellent! Now check your email to confirm your subscription.