Dynamic How To Create Text Spans in Webflow CMS Dynamic Text Elements

Jakes van Eeden
Milk Moon Studio
Published in
6 min readMar 20, 2023

In this how-to we’ll look at creating text spans in dynamic text elements in Webflow with a little custom code and a marker around the text in the Webflow CMS field.

This is one feature that’s been missing for quite a while, well actually since the day Collection Lists launched in Webflow. Doing it the no-code way is near impossible, unless you create a bunch of fields and string them together, but only really works for headings and it’s not flexible.

In this example, we’ll just be using a small amount of custom code, and a marker that you can add in your CMS before and after the text you need the span for. We’re Milk Moon Studio is a small Webflow studio and we’re all Webflow designers, so we like low-code, when we can’t get no-code, and you definitely don’t need to be a Webflow expert for this one, it’s pretty much copy and paste.

So, in our use case, we just wanted to change the text colour and make it really easy for the client to manage by just adding a marker to the CMS. Initially anyway, we’ll get to more complicated use-cases later

Create the styles

We started off by creating the text style we want to use in the span, like I said, just a change in text colour, but you can go wild. In this case it was text-color-green and as you can imagine the colour was just green. Just remember the rules when it comes to stacking CSS styles, only override what you want the span to apply.

Style the dynamic text span in the Webflow CMS

Load jQuery

Next you’re going to need to add script to the <head> code of the project.

<!-- Adds jquery to create text spans on CMS pages -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

Add custom code to the page

Our next step is to add the custom script to the pages that need to have the CMS spans, in our case that was just the CMS template pages for services. You need to add this to the “Before </body> tag” section as the text will need to load before the script runs.

<script>
document.addEventListener('DOMContentLoaded', function() {
// Select all h1 and h2 elements, and all elements with the class 'services-hero_h1'
const headings = document.querySelectorAll('h1, h2, .services-hero_h1');

// Iterate over each heading element
headings.forEach(function(heading) {
// Get the heading content
const headingContent = heading.innerHTML;

// Replace the marker (e.g., '%%') with a span with the 'text-color-green' class
const wrappedContent = headingContent.replace(/%%(.*?)%%/gi, function(_, match) {
return `<span class="text-color-green">${match}</span>`;
});

// Replace the original content with the wrapped content
heading.innerHTML = wrappedContent;
});
});
</script>‍

If you look at the code you’ll see that in my case I wanted all h1’s all h2 and text styled as .services-hero_h1. You’re looking for line 4:
const headings = document.querySelectorAll(‘h1, h2, .services-hero_h1’);

So over here, just add your styles or tags.

Mark the text in the CMS

Finally, just add the marker around the text in the CMS. We used %% as the marker.

Naturally you won’t see the span in the Designer, but after you publish it’ll work just fine when the code run. There’s markup in the code, but what the script is doing is looking for the text elements you specified, then checking for the marker %%, and then adding the span around the text inside the marker.

Text Span Marker in the Designer
Webflow CMS Text Span on the published site

Two Spans!

If you’re keeping things simple, that’s about it. We did however realise that the contrast on the green was way to light if we had it on a white background, so we created another span with a darker shade of green and added two styles we could apply to the text elements, one for green text on a dark background and one for green text on a white background. So now we had two additional text styles the script had to check for and two styled text spans that needed to be applied if the text was either in a light or dark background. To help the script identify text on white we added: .text-is-on-white as a style, and for text on dark, the apply named: .text-is-on-dark.

For text on white we created a new darker green style: .text-color-green-on-white

We know, we really need to get better at naming styles.

Anyhow, the code had to be updated to cycle through everything and add the new span as well, so here’s the new code:

This just replaced the previous code before the </body> tag. And there you have it, some additional code to give you an idea of what you can do if things get more complex.

<script>
document.addEventListener('DOMContentLoaded', function() {
// Select all h1 and h2 elements, and all elements with the class 'services-hero_h1', 'text-is-on-dark' or 'text-is-on-white'
const headings = document.querySelectorAll('h1, h2, .services-hero_h1, .text-is-on-dark, .text-is-on-white');

// Iterate over each heading element
headings.forEach(function(heading) {
// Get the heading content
const headingContent = heading.innerHTML;

// Determine the appropriate span class based on the element's class
const spanClass = heading.classList.contains('text-is-on-white') ? 'text-color-green-on-white' : 'text-color-green';

// Replace the marker (e.g., '%%') with a span with the appropriate class
const wrappedContent = headingContent.replace(/%%(.*?)%%/gi, function(_, match) {
return `<span class="${spanClass}">${match}</span>`;
});

// Replace the original content with the wrapped content
heading.innerHTML = wrappedContent;
});
});
</script>‍

Hide the text if the page flashes %% on load

Finally, a last bit of help, if you have a very large or busy page, you might see the %% marker flash and then be replaced, basically because the text is loading and only then after that the script runs, we only had this on one very large page, but a simple solution is to add a class that hides the text till the script has run and then have the script make the text visible, something like this:

<style>
.hide-until-loaded {
visibility: hidden;
}
</style>‍

You’ll need to add the new style in the <head> and then apply the class to the elements you want to hide and show (in our case that was the h1, h2 and .services-hero_h1), then update you script with the bit that unhides the text.

<script>
document.addEventListener('DOMContentLoaded', function() {
// Select all h1 and h2 elements, and all elements with the class 'services-hero_h1'
const headings = document.querySelectorAll('h1, h2, .services-hero_h1');

// Iterate over each heading element
headings.forEach(function(heading) {
// Get the heading content
const headingContent = heading.innerHTML;

// Replace the marker (e.g., '%%') with a span with the 'text-color-green' class
const wrappedContent = headingContent.replace(/%%(.*?)%%/gi, function(_, match) {
return `<span class="text-color-green">${match}</span>`;
});

// Replace the original content with the wrapped content
heading.innerHTML = wrappedContent;

// Remove the 'hide-until-loaded' class
heading.classList.remove('hide-until-loaded');
});
});
</script>‍

We really hope that help you with what has by now become a bit of a sorely missed feature. If you have any question, fire them in the comments. We might do a quick video at some stage, so stay tuned, and if you’re looking for more how-to’s check out the section on the blog.

Originally published at https://www.milkmoonstudio.com.

--

--

Jakes van Eeden
Milk Moon Studio

South African, small time Webflow dev, analytics enthusiast and tech lover. I write on behalf of our Webflow design and dev agency milkmoonstudio.com