Typographic rows are separated by thin lines. On desktop, hovering over a row triggers a floating photo that smoothly tracks the cursor. On mobile, tapping a row reveals the image inline beneath the text. Everything is driven by two HTML widgets and a set of CSS classes assigned in Elementor's Advanced tab.
.zip archive containing the layout JSON.
.json templates directly to the Media Library. To work around this:
- Download the
.zipfile above and extract the.jsonfile on your computer. - In WordPress, navigate to Templates → Saved Templates.
- Click Import Templates at the top, select your extracted
.jsonfile, and click Import Now. - Once imported, simply load the template inside your Elementor canvas by opening the template library folder icon and choosing your saved template!
Architecture tree
This is the Elementor widget hierarchy. Place the Styles Widget first and the Script Widget last within your parent column container.
Services Section (Elementor Section) └── Parent (single Column inside Section) │ ├── Styles Widget (HTML Widget) ← FIRST element inside Parent │ ├── Row 1 (Inner Section · Advanced CSS Classes: service-row) │ ├── Number (Column) │ │ └── Label (Text Widget) │ ├── Name (Column) │ │ └── Title (Heading Widget · Advanced CSS Classes: service-title) │ ├── Description (Column) │ │ └── Body (Text Widget · Advanced CSS Classes: service-body) │ └── Image (Column · Advanced CSS Classes: service-img-col) │ └── Thumbnail (Image Widget · Advanced CSS Classes: service-img) │ ├── Row 2 (Inner Section · Advanced CSS Classes: service-row) │ ├── Number (Column) │ │ └── Label (Text Widget) │ ├── Name (Column) │ │ └── Title (Heading Widget · Advanced CSS Classes: service-title) │ ├── Description (Column) │ │ └── Body (Text Widget · Advanced CSS Classes: service-body) │ └── Image (Column · Advanced CSS Classes: service-img-col) │ └── Thumbnail (Image Widget · Advanced CSS Classes: service-img) │ ├── Row 3 (Inner Section · Advanced CSS Classes: service-row) │ └── Same structure — all rows use the exact same classes │ └── Script Widget (HTML Widget) ← LAST element inside Parent
CSS class reference
Assign these classes in the Advanced → CSS Classes tab of each Elementor item. Match the targets precisely for the widgets to be identified by the script.
| Element | CSS class | Applied to |
|---|---|---|
| Every row Inner Section | service-row | Inner Section Settings |
| Image Column (inside row) | service-img-col | Column Settings |
| Image widget (Thumbnail) | service-img | Image Widget Settings |
| Title Heading Widget | service-title | Heading Widget Settings |
| Body Text Widget | service-body | Text Editor Widget Settings |
Step-by-step build guide
Add a new Section to your page containing a single column. All rows and both HTML code widgets must live directly inside this column (the "Parent" column).
Drag an HTML widget to the very top of the Parent column. This will act as the Styles Widget. Leave it empty for now; you will add the CSS code in the next section.
Insert an Inner Section below the Styles Widget and set it to a 4-column layout. Open the Inner Section settings, go to the Advanced tab, and set the CSS Classes field to: service-row
Add the visible columns inside Row 1:
- Add a Text Editor widget for your numbers (e.g.
01).
- Add a Heading widget.
- In its Advanced tab, set the CSS Class to:
service-title
- Add a Text Editor widget.
- In its Advanced tab, set the CSS Class to:
service-body
Add the 4th column inside Row 1 (e.g. 4% width):
- Click the column border to edit the column itself.
- In the Advanced tab, set the CSS Class to:
service-img-col
- Drag an Image widget inside this column and select your image from the Media Library.
- In the Advanced tab, set the CSS Class to:
service-img
Duplicate Row 1 to create Row 2 and Row 3. The CSS classes are preserved automatically. Simply swap the images and change the text content.
Drag a second HTML widget to the very bottom of the Parent column (below all row sections). This is your Script Widget.
The two code widgets
Paste the corresponding codes into the HTML widgets created in the steps above.
Widget 1 — Styles Widget (paste inside the first HTML widget)
Widget 2 — Script Widget (paste inside the second HTML widget)
Mobile behaviour & touch screens
On touch screens, the floating cursor follow layout is disabled. Instead, tapping a card expands the max-height of the images column to reveal the image stacked vertically inline below the card text content.
Elementor Breakpoint Setup
Switch to the Mobile Breakpoint viewport within the Elementor editor. For each card section:
- Set the Number, Name, and Description columns to 100% width so they stack vertically.
- Set the Image column to 100% width.
The stylesheet handles hiding/expanding the height on tap, and the script handles the click toggle. Only one card section can remain expanded at any time.
Troubleshooting
Ensure that the CSS class service-img-col is applied directly to the Column Settings containing the images, and not inside individual image widgets. The Styles Widget must also load at the very top of your parent column container so it applies initial hiding rules before widgets render.
Verify that your Text and Heading widgets have the classes service-title and service-body applied. The stylesheet forces elements with these classes to transition their colors properly when the parent row is hovered.
Check that the Script Widget is placed as the very last element in the Parent column. Open your browser console (F12) to ensure there are no other JavaScript errors on the page blocking execution.
Pre-publish checklist
Confirm these technical steps before publishing the page:
How it works — layers and pseudo-elements
The page layout is structured to maintain a clean layout context. Elements are positioned and hidden using standard z-index configurations:
| Selector | What it does |
|---|---|
| .service-row | Main row container. Triggers transition padding on hover to animate sliding to the right. |
| .hr-float-img | Injected dynamic overlay containing the image. Fixed position with a high z-index that follows cursor movement on desktop using lerp (linear interpolation). Hidden completely on mobile. |
| .service-img-col | Standard image container widget. Collapsed on desktop and expanded dynamically on mobile using max-height animation transitions. |