Since the article about image-friendly Squarespace accordion got so much interest also many upgrade requests I decided to rewrite this snippet and make it richer.

What does the new script offer vs the old script?

  1. You can add images in your accordion just by adding a link that points to an image
  2. You can also add videos just by adding a link that points towards an uploaded video
  3. You can add also embeded youtube videos just by adding a link that points towards an embed youtube link

How about adding text on the left or right of the image/video?

Now you are able to do that also ! I will explain later how to do it.

What about images/video that go beyond the screen?

It’s all taken care of. Videos and images will always stay in the boundaries of your screen.

The code

document.querySelectorAll('.accordion-item__description').forEach((item) => {
  const imageExtRegExp = /\.(jpg|jpeg|png|webp|avif|gif|svg)$/;
  const videoExtRegExp = /\.(mp4|avi|wmv|mov|flv|mkv|webm|vob|ogv|m4v|3gp|3g2|mpeg|mpg|m2v|m4v|svi|3gpp|3gpp2|mxf|roq|nsv|flv|f4v|f4p|f4a|f4b)$/;
  const youtubevimeoRegExp = /(?:https?:)?\/{2}(?:www\.)?youtu\.?be(?:\/|\.com\/watch\?v\=|\.com\/v\/|\.com\/embed\/)?([\w-]*)[?&]?.*|(?:http:|https:|)\/\/(?:player.|www.)?vimeo\.com\/(?:video\/|embed\/|watch\?\S*v=|v\/)?(\d*)/; 
  item.querySelectorAll('a').forEach((link) => {
      const linkParent = link.parentElement;
      const nodes = linkParent.childNodes;
      const columnize = () => {
          nodes.forEach(node => {
              if(node.nodeType === Node.TEXT_NODE) {
                  linkParent.querySelector('*').style.flexBasis = '50%';
                  linkParent.style.display = 'flex';
                  linkParent.style.alignItems = 'center';
                  linkParent.style.gap = '15px';

      if(imageExtRegExp.test(link.href)) {
          const wrapperLink = link;
          const imgSrc = link.href;
          const hasLink = /[\[.*\]]/.test(linkParent.textContent);
          const img = document.createElement('img');
          const linkHref = linkParent.textContent.replace(/(.+)\[(.+)\](.*)/, '$2');
          img.src = imgSrc;
          img.alt = link.innerText.replace('/\(.*?\)/','');
          img.style = 'min-width: 0; max-width: 100%';

          if(hasLink) { 
              wrapperLink.innerHTML = '';
              wrapperLink.href = linkHref;
          else { link.replaceWith(img); }

          nodes.forEach(node => {
              if(node.nodeType === Node.TEXT_NODE) {
                  if(/[\[.*\]]/.test(node.nodeValue)) {
                      node.nodeValue = node.nodeValue.replace(/\[.*\]/, '');

                  if(node.nodeValue.trim().length && !/\[.*\]/.test(node.nodeValue)) {
                      linkParent.querySelector('*').style.flexBasis = '50%';
                      linkParent.style.display = 'flex';
                      linkParent.style.alignItems = 'center';
                      linkParent.style.gap = '15px';
      else if(videoExtRegExp.test(link.href)) {
          const videoExt = link.href.match(videoExtRegExp)[1];
          const videoTag = `
              <video controls style="max-width: 100%">
                  <source type="video/${videoExt}" src="${link.href}"></source>
          link.insertAdjacentHTML('afterend', videoTag);
      else if(youtubevimeoRegExp.test(link.href)) {
          const iframeTag = `<iframe src="${link.href}" width="100%" style="aspect-ratio:16/9" />`;
          link.insertAdjacentHTML('afterend', iframeTag);
  item.querySelectorAll('p:empty').forEach(p => p.remove());

This script goes into the Injection panel(not available on personal plans). You can find Code injection link on top-left. You can also find it in the Settings menu in case Code Injection is not on top left corner.


First step is to write the alternative text for the image or just placeholder text for the video.

Second step is to select that text:

Third step is to put a link on it, but not any kind of link. Instead of selecting Web Address, you will select File and then you select an uploaded image or video.

Now you just select the image/video from your list or upload new file, then close this popup, then save and finally hit the apply button.

Let’s upload a video also:

How do I add a link around the image?

That requires more work from you. You have to add after the link in brackets the url for the link but BE CAREFUL. You have to add a space after the link that you just created and write that URL in brackets after that.

You can also observe that the text in brackets does not have an underline, so that is also a good indicator that it is not inside the link but after it. So this is the HTML that is created afterwards:

How about adding also a text before or after it?

It is simple, you just continue writing the text after all this or before the link(make sure it does not get tangled in the link, so watch for that underline).

The result looks like this:

So how do I add an Embeded youtube video?

You just choose instead of File the Web Address and introduce an embed code from youtube:

Watch out

Sometimes the bracket text gets entangled in the link, you can see that it got underlined:

In these cases revisit the item select the bracket text and remove only from that the link:

Final words

You can also find the Javascript code that you need to insert in the Injection panel, here.

I am opened for new suggestions, this plugin will have multiple future versions. So hit me up with any questions, suggestions and I will respond in the comments section. Also don’t forget to like and subscribe.

Also you can find the video explanation of how you can add images and links around images and videos and embedded Youtube videos from the accordion:

How useful was this post?

Click on a star to rate it!

Average rating 5 / 5. Vote count: 1

No votes so far! Be the first to rate this post.

Categorized in: