And if you’re building your site in Divi, getting it right is harder than it should be. Here’s why, and what to do about it.
The real problem: the default grid is decent, but rigid
The problem isn’t that it’s ugly. The problem is that it’s rigid.
The catch is where the real flexibility lives. There are two versions of the grid, and the capable one — Course Grid 2.0, with its different skins, card layouts, filters and styling controls — is built for the block editor. LearnDash’s own documentation says as much, and notes the options are more limited when you use shortcodes instead. And as a Divi user, shortcodes are exactly where you’re steered: their docs are explicit that with a page builder you use shortcodes, not blocks, and that Divi can’t edit LearnDash’s dynamic content the way an Elementor add-on can. So the styling-rich version of the grid sits on the other side of a wall from how you actually build.
The result, for a lot of LearnDash-on-Divi sites, is a course grid that’s plain, hard to customise, and clearly not part of the designed site around it — sitting on the most important browsing page you have.
What a good course grid actually needs
- It has to look like the rest of your site. A polished homepage followed by a generic grid of course boxes breaks the spell. Consistency is what signals “this is a real, professional course platform.”
- It has to be scannable. Someone browsing should be able to take in their options quickly — clear titles, a thumbnail, and the few details that help them choose.
- It should show the right information per course. Not every course needs the same labels. The useful details — length, level, price, whatever matters for yours — should be yours to set.
- It has to work on a phone. Most browsing happens on mobile, so the grid needs to reflow cleanly to smaller screens.
What you can do to improve it yourself
First, the shortcode. The grid is generated by [ld_course_list] which takes parameters to control the output — num for how many courses show, and orderby / order to sort them:
[ld_course_list num="12" orderby="title" order="ASC"]
Paste the shortcode in the Text module, then in Advanced › Custom CSS (the “Free Form” / main CSS box) add:
/* Tidy, even spacing between cards */
selector .ld-course-list-items {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 14px;
}
selector .ld_course_grid{
max-width:100%;
}
/* The card itself — equal height, soft border, rounded */
selector .ld_course_grid article.thumbnail.course {
display: flex;
flex-direction: column;
height: 100%;
border: 0px solid #1f2130;
border-radius: 6px;
box-shadow: 0 2px 18px 0 rgba(51, 51, 51, .23);
}
/* The image */
selector .ld_course_grid img {
border-radius:5px 5px 0 0;
}
/* The caption area (title + button) */
selector .ld_course_grid .thumbnail .caption {
display: flex;
flex-direction: column;
flex: 1;
padding: 26px;
}
/* The title in caption area */
selector .ld_course_grid .thumbnail .caption .entry-title{
margin-bottom: 16px !important;
}
/* The ribbon — shared shape for all three states */
selector .ld_course_grid .thumbnail.course .ribbon {
padding: 6px 26px;
border-radius: 4px;
border-bottom-left-radius:0;
font-weight: 600;
color: #fff;
}
/* The ribbon has three states, each with its own class —
style them separately so you don't flatten them into one colour:
.ribbon = the price (e.g. "250")
.ribbon.free = free courses
.ribbon.enrolled = courses the visitor is already enrolled in */
selector .ld_course_grid .thumbnail.course .ribbon:not(.free):not(.enrolled){
background: #c0392b; /* price */
}
selector .ld_course_grid .thumbnail.course .ribbon:not(.free):not(.enrolled)::before{
border-top-color:#c0392b;
border-right-color:#c0392b;
}
selector .ld_course_grid .thumbnail.course .ribbon.free {
background: #20ad96; /* free — green */
}
selector .ld_course_grid .thumbnail.course .ribbon.free::before{
border-top-color:#20ad96;
border-right-color:#20ad96;
}
selector .ld_course_grid .thumbnail.course .ribbon.enrolled {
background: #1f2130; /* enrolled — blue */
}
selector .ld_course_grid .thumbnail.course .ribbon.enrolled::before{
border-top-color:#1f2130;
border-right-color:#1f2130;
}
/* The button — push it to the bottom so every card lines up */
selector .ld_course_grid .ld_course_grid_button {
margin-top: auto !important;
}
selector .ld_course_grid .thumbnail.course .btn-primary {
padding:10px;
background-color:#20ad96;
color:#fff
}
/* Reflow to fewer columns on smaller screens */
@media (max-width: 980px) {
selector .ld-course-list-items { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 600px) {
selector .ld-course-list-items { grid-template-columns: 1fr; }
}
One honest caveat: LearnDash’s markup can differ between versions, so check your own grid to be safe — right-click a card › Inspect, confirm the class names match, and adjust if needed. And note what CSS can’t give you: real visual, in-Builder control. You’re still hand-writing styles to fight fixed markup rather than designing the card the way you design everything else in Divi — and the richer skin-and-card system stays locked in the block editor. Which is exactly where the next option comes in.
Your three options, honestly
The fix: a course grid module built for Divi
- It’s native to Divi. The grid lives in the Builder alongside everything else you design, so it matches your site instead of standing out from it. No Gutenberg detour, no settling for the limited shortcode.
- You style it visually. Columns, spacing, fonts, colours — set the way you set everything else in Divi, with the module’s own settings panels.
- You control the details, and how they look, in Divi. The module gives you three fully customisable meta fields you set individually for each course, from the course’s own edit screen — duration and level on one, format and price on another. But the real difference from the default isn’t just which details show; it’s that you’re designing the card visually in the Builder rather than filling in back-end fields and styling around fixed markup. Leave a field blank and nothing shows. It’s your call, course by course.
Getting it right
- Keep the cards consistent. Equal-looking cards, aligned details, and uniform thumbnails read as considered and trustworthy. Mismatched heights and stray fields read as unfinished.
- Show only what helps the decision. Use the meta fields for the details that genuinely help someone choose — not everything you could display. A clean card beats a cluttered one.
- Design it as a real page, not an afterthought. Give the grid a proper heading, a line of intro if it helps, and room to breathe. It’s a browsing experience, not just a list.
- Check it on mobile. Scroll it on your phone and make sure the cards reflow cleanly and stay tappable.
The takeaway
A Divi-native course grid module solves that: a grid you design visually, that matches your site, with the details you control per course. It turns your most important browsing page from a generic afterthought into something that actually invites people in.
Working on your individual course pages too? That’s a different page with its own default limitations — our free Powdi Course Page Builder for LearnDash and Divi plugin handles those. We’ve covered it in How to Design Your LearnDash Course Pages with Divi.

