htmlcsswordpressforms

Replace Contact Form 7 checkboxes with custom CSS image checkboxes


I've got a contact form created with Contact Form 7 for WordPress that contains checkboxes. I'd like to style them to be image checkboxes to make them stand out a bit more. I actually found a nice checkbox style that I've already created on the page. I just need some help with integrating it into Contact Form 7.

Here is the specific page it's on: https://www.mattrittman.com/animation-licensing-v2/

Essentially just wanting what's in the white box to replace the standard checkboxes in the form below on that page.

Here is the code snippet for my custom image checkboxes:

* {
  font-family: Lato;
  margin: 0;
  padding: 0;
  --transition: 0.15s;
  --border-radius: 0.5rem;
  --background: #0077ef;
  --box-shadow: #0077ef;
}

.cont-main {
  display: flex;
  flex-wrap: wrap;
  align-content: left;
  justify-content: left;
}

.cont-checkbox {
  width: 150px;
  height: 100px;
  border-radius: var(--border-radius);
  box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
  background: white;
  transition: transform var(--transition);
  margin: 0 8px;
}

.cont-checkbox:first-of-type {
  margin-bottom: 0.75rem;
  /*margin-right: 0.75rem;*/
}

.cont-checkbox:active {
  transform: scale(0.9);
}

.cont-checkbox input {
  display: none;
}

.cont-checkbox input:checked + label {
  opacity: 1;
  box-shadow: 0 0 0 3px var(--background);
}

.cont-checkbox input:checked + label img {
  -webkit-filter: none; /* Safari 6.0 - 9.0 */
  filter: none;
}

.cont-checkbox input:checked + label .cover-checkbox {
  opacity: 1;
  transform: scale(1);
}

.cont-checkbox input:checked + label .cover-checkbox svg {
  stroke-dashoffset: 0;
}

.cont-checkbox label {
  display: inline-block;
  cursor: pointer;
  border-radius: var(--border-radius);
  overflow: hidden;
  width: 100%;
  height: 100%;
  position: relative;
  opacity: 0.6;
}

.cont-checkbox label img {
  width: 100%;
  height: 70%;
  object-fit: cover;
  clip-path: polygon(0% 0%, 100% 0, 100% 81%, 50% 100%, 0 81%);
  -webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */
  filter: grayscale(100%);
}

.cont-checkbox label .cover-checkbox {
  position: absolute;
  right: 4px;
  top: 3px;
  z-index: 1;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--box-shadow);
  border: 2px solid #fff;
  transition: transform var(--transition),
    opacity calc(var(--transition) * 1.2) linear;
  opacity: 0;
  transform: scale(0);
}

.cont-checkbox label .cover-checkbox svg {
  width: 11px;
  height: 10px;
  display: inline-block;
  vertical-align: top;
  fill: none;
  margin: 4px 0 0 3px;
  stroke: #fff;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 16px;
  transition: stroke-dashoffset 0.4s ease var(--transition);
  stroke-dashoffset: 16px;
}

.cont-checkbox label .info {
  text-align: center;
  margin-top: -1.6rem;
  font-weight: 600;
  font-size: 0.8rem;
  color: #000;
}
<div class="cont-main">
  <div class="cont-checkbox">
    <input type="checkbox" id="myCheckbox-1" />
    <label for="myCheckbox-1">
      <img
        src="https://www.mattrittman.com/wp-content/uploads/2024/08/glock-thumb.jpg"
      />
      <span class="cover-checkbox">
        <svg viewBox="0 0 12 10">
          <polyline points="1.5 6 4.5 9 10.5 1"></polyline>
        </svg>
      </span>
      <div class="info">How a Glock Works</div>
    </label>
  </div>
  <div class="cont-checkbox">
    <input type="checkbox" id="myCheckbox-2" />
    <label for="myCheckbox-2">
      <img
        src="https://www.mattrittman.com/wp-content/uploads/2024/08/ar15-thumb.jpg"
      />
      <span class="cover-checkbox">
        <svg viewBox="0 0 12 10">
          <polyline points="1.5 6 4.5 9 10.5 1"></polyline>
        </svg>
      </span>
      <div class="info">How an AR-15 Works</div>
    </label>
  </div>
    <div class="cont-checkbox">
    <input type="checkbox" id="myCheckbox-3" />
    <label for="myCheckbox-3">
      <img
        src="https://www.mattrittman.com/wp-content/uploads/2024/08/gas-system-thumb.jpg"
      />
      <span class="cover-checkbox">
        <svg viewBox="0 0 12 10">
          <polyline points="1.5 6 4.5 9 10.5 1"></polyline>
        </svg>
      </span>
      <div class="info">AR-15 Gas System</div>
    </label>
  </div>
    <div class="cont-checkbox">
    <input type="checkbox" id="myCheckbox-4" />
    <label for="myCheckbox-4">
      <img
        src="https://www.mattrittman.com/wp-content/uploads/2024/08/revolver-thumb.jpg"
      />
      <span class="cover-checkbox">
        <svg viewBox="0 0 12 10">
          <polyline points="1.5 6 4.5 9 10.5 1"></polyline>
        </svg>
      </span>
      <div class="info">How a Revolver Works</div>
    </label>
  </div>
    <div class="cont-checkbox">
    <input type="checkbox" id="myCheckbox-5" />
    <label for="myCheckbox-5">
      <img
        src="https://www.mattrittman.com/wp-content/uploads/2024/08/shotgun-thumb.jpg"
      />
      <span class="cover-checkbox">
        <svg viewBox="0 0 12 10">
          <polyline points="1.5 6 4.5 9 10.5 1"></polyline>
        </svg>
      </span>
      <div class="info">How a Shotgun Works</div>
    </label>
  </div>
    <div class="cont-checkbox">
    <input type="checkbox" id="myCheckbox-6" />
    <label for="myCheckbox-6">
      <img
        src="https://www.mattrittman.com/wp-content/uploads/2024/08/kar98k-thumb.jpg"
      />
      <span class="cover-checkbox">
        <svg viewBox="0 0 12 10">
          <polyline points="1.5 6 4.5 9 10.5 1"></polyline>
        </svg>
      </span>
      <div class="info">How a Kar98k Works</div>
    </label>
  </div>
    <div class="cont-checkbox">
    <input type="checkbox" id="myCheckbox-7" />
    <label for="myCheckbox-7">
      <img
        src="https://www.mattrittman.com/wp-content/uploads/2024/08/ak47-thumb.jpg"
      />
      <span class="cover-checkbox">
        <svg viewBox="0 0 12 10">
          <polyline points="1.5 6 4.5 9 10.5 1"></polyline>
        </svg>
      </span>
      <div class="info">How an AK-47 Works</div>
    </label>
  </div>
    <div class="cont-checkbox">
    <input type="checkbox" id="myCheckbox-8" />
    <label for="myCheckbox-8">
      <img
        src="https://www.mattrittman.com/wp-content/uploads/2024/08/ac-thumb.jpg"
      />
      <span class="cover-checkbox">
        <svg viewBox="0 0 12 10">
          <polyline points="1.5 6 4.5 9 10.5 1"></polyline>
        </svg>
      </span>
      <div class="info">How A/C Works</div>
    </label>
  </div>
</div>
</div>

Here is the code that CF7 generates:

<span class="wpcf7-form-control-wrap" data-name="videos">
    <span class="wpcf7-form-control wpcf7-checkbox wpcf7-validates-as-required">
        <span class="wpcf7-list-item">
            <label>
                <input type="checkbox" name="videos[]" value="How a Glock Works" />
                <span class="wpcf7-list-item-label">How a Glock Works</span>
            </label>
        </span>
        <span class="wpcf7-list-item">
            <label>
                <input type="checkbox" name="videos[]" value="How an AR-15 Works" />
                <span class="wpcf7-list-item-label">How an AR-15 Works</span>
            </label>
        </span>
        <span class="wpcf7-list-item">
            <label>
                <input type="checkbox" name="videos[]" value="AR-15 Gas System" />
                <span class="wpcf7-list-item-label">AR-15 Gas System</span>
            </label>
        </span>
        <span class="wpcf7-list-item">
            <label>
                <input type="checkbox" name="videos[]" value="How a Revolver Works" />
                <span class="wpcf7-list-item-label">How a Revolver Works</span>
            </label>
        </span>
        <span class="wpcf7-list-item">
            <label>
                <input type="checkbox" name="videos[]" value="How a Shotgun Works" />
                <span class="wpcf7-list-item-label">How a Shotgun Works</span>
            </label>
        </span>
        <span class="wpcf7-list-item">
            <label>
                <input type="checkbox" name="videos[]" value="How a Kar98k Works" />
                <span class="wpcf7-list-item-label">How a Kar98k Works</span>
            </label>
        </span>
        <span class="wpcf7-list-item">
            <label>
                <input type="checkbox" name="videos[]" value="How an AK-47 Works" />
                <span class="wpcf7-list-item-label">How an AK-47 Works</span>
            </label>
        </span>
        <span class="wpcf7-list-item">
            <label>
                <input type="checkbox" name="videos[]" value="How Air Conditioning Works" />
                <span class="wpcf7-list-item-label">How Air Conditioning Works</span>
            </label>
        </span>
    </span>
</span>


Solution

  • Remember that this is essentially a styling exercise. You want to style the CF7 checkboxes so that they look like the pretty ones. But of course the style rules for the pretty checkboxes are built around the HTML structure of those checkboxes. So the first challenge is to alter the HTML structure of the CF7 form to match the pretty structure as closely as possible.

    If you turn off the option “Wrap each item with a label element” when generating your checkboxes (or remove the use_label_element option from the generated CF7 checkbox tag), the resulting HTML code will be very close in structure to the code which presents your pretty checkboxes. Examine this comparison:

    CF7 structure

    <span class="wpcf7-form-control-wrap" data-name="checkbox-889">
    
      <span class="wpcf7-form-control wpcf7-checkbox">
        <span class="wpcf7-list-item first">
          <input type="checkbox" name="checkbox-889[]" value="one">
          <span class="wpcf7-list-item-label">one</span>
        </span>
        <span class="wpcf7-list-item">
          <input type="checkbox" name="checkbox-889[]" value="two">
          <span class="wpcf7-list-item-label">two</span>
        </span>
        <span class="wpcf7-list-item last">
          <input type="checkbox" name="checkbox-889[]" value="three">
          <span class="wpcf7-list-item-label">three</span>
        </span>
      </span>
    
    </span>
    

    Pretty structure

    <div class="cont-main">
      <div class="cont-checkbox">
        <input type="checkbox" id="myCheckbox-1" />
        <label for="myCheckbox-1"> ... </label>
      </div>
      <div class="cont-checkbox">
        <input type="checkbox" id="myCheckbox-2" />
        <label for="myCheckbox-2"> ... </label>
      </div>
      <div class="cont-checkbox">
        <input type="checkbox" id="myCheckbox-3" />
        <label for="myCheckbox-3"> ... </label>
      </div>
    </div>
    

    The problem is that CF7 in this scenario does not generate <label> elements, instead it generates <span class="wpcf7-list-item-label">. When a <label> is linked to a checkbox, clicking the label toggles the checkbox — this is essential to get the pretty checkboxes working right, but the <span> generated by CF7 won’t do this. My recommendation would be to use Javascript to convert these <span>s into <label>s.

    The labels for the pretty each contain an image, and SVG and some text. Because there is no way to add these in the CF7 form editor, you will need to use Javascript to insert these into your new <label> elements.

    Here is a snippet which demonstrates both converting the <span> to a <label>, and inserting the custom contents:

    const contents = [
      {title: 'How a Glock Works', img: 'glock-thumb.jpg'},
      {title: 'How an AR-15 Works', img: 'ar15-thumb.jpg'},
      {title: 'AR-15 Gas System', img: 'gas-system-thumb.jpg'}
    ]
    const checkboxes = document.querySelectorAll('[data-name=checkbox-889] .wpcf7-list-item')
    let x = 0;
    checkboxes.forEach(cb => {
      const i = cb.querySelector('input')
      i.id = `cb889-${i.value}`         /* assign the checkbox a unique id */
      const l = cb.querySelector('.wpcf7-list-item-label')
      const nl = []                     /* array for the <label> markup */
      nl.push(`<label for="${i.id}" class="wpcf7-list-item-label">`)
      nl.push(`<img src="https://www.mattrittman.com/wp-content/uploads/2024/08/${contents[x].img}"/>`)
      nl.push(`<span class="info wpcf7-list-item-label"> ${contents[x].title}</span>`)
      nl.push('</label>')
      l.insertAdjacentHTML('afterend', nl.join('')) /* insert the <label> */
      l.remove()                        /* remove the <span> */
      x++;
    })
    label {
      -webkit-user-select: none;
      user-select: none;
    }
    
    .wpcf7-list-item-label img {
      width: 50px;
    }
    <p>Click on the image or text to toggle the corresponding checkbox</p>
    
    <span class="wpcf7-form-control-wrap" data-name="checkbox-889">
    
      <span class="wpcf7-form-control wpcf7-checkbox">
        <span class="wpcf7-list-item first">
          <input type="checkbox" name="checkbox-889[]" value="one">
          <span class="wpcf7-list-item-label"></span>
        </span>
        <span class="wpcf7-list-item">
          <input type="checkbox" name="checkbox-889[]" value="two">
          <span class="wpcf7-list-item-label"></span>
        </span>
        <span class="wpcf7-list-item last">
          <input type="checkbox" name="checkbox-889[]" value="three">
          <span class="wpcf7-list-item-label"></span>
        </span>
      </span>
    
    </span>

    Then it should just be a matter of adding some selectors to the style rules you already have to make them apply to the CF7 structure as well. So, for example, take the following style rule:

    .cont-checkbox label {
      display: inline-block;
      cursor: pointer;
      border-radius: var(--border-radius);
      overflow: hidden;
      width: 100%;
      height: 100%;
      position: relative;
      opacity: 0.6;
    }
    

    The equivalent selector for the CF7 structure would be .wpcf7-list-item-label .wpcf7-list-item-label, so you would just change the selector in the style rule to:

    .cont-checkbox label, .wpcf7-list-item-label .wpcf7-list-item-label {
      ...
    }