Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Client-First — Version 2.1

Style Guide

Client-First is a set of guidelines and strategies created by Finsweet to help you build Webflow websites.

Structure Classes

Defined and flexible core structure we can use on all or most pages.

page-wrapper
main-wrapper
container-small
container-medium
container-large
padding-global
padding-section-small
padding-section-medium
padding-section-large
button-group

Headings

HTML tags define default Heading styles. Use Heading classes when the typography style doesn't match the default HTML tag.

H1

Sample text helps you understand how real text may look. Sample text is being used as a placeholder.

heading-style-h1

Sample text helps you understand how real text may look. Sample text is being used as a placeholder.

H2

Sample text is being used as a placeholder. Sample text helps you understand how real text may look.

heading-style-h2

Sample text is being used as a placeholder. Sample text helps you understand how real text may look.

H3

Sample text helps you understand how real text may look on your website. Sample text is being used as a placeholder for real text that is normally present.

heading-style-h3

Sample text helps you understand how real text may look on your website. Sample text is being used as a placeholder for real text that is normally present.

H4

Sample text is being used as a placeholder. Sample text helps you understand how real text may look. Sample text is being used as a placeholder for real text that is normally present.

heading-style-h4

Sample text is being used as a placeholder. Sample text helps you understand how real text may look. Sample text is being used as a placeholder for real text that is normally present.

H5
Sample text is being used as a placeholder. Sample text helps you understand how real text may look. Sample text is being used as a placeholder for real text that is normally present. Sample text helps you understand how real text may look.
heading-style-h5
Sample text is being used as a placeholder. Sample text helps you understand how real text may look. Sample text is being used as a placeholder for real text that is normally present. Sample text helps you understand how real text may look.
H6
Sample text is being used as a placeholder for real text that is normally present. Sample text helps you understand how real text may look. Sample text is being used as a placeholder for real text that is normally present. Sample text helps you understand how real text may look.
heading-style-h6
Sample text is being used as a placeholder for real text that is normally present. Sample text helps you understand how real text may look. Sample text is being used as a placeholder for real text that is normally present. Sample text helps you understand how real text may look.

Other HTML Tags

HTML tags define default text styles.

All paragraphs

Sample text is being used as a placeholder for real text that is normally present. Sample text helps you understand how real text may look on your website. Sample text is being used as a placeholder for real text.

All links
All Links
All quotes
Sample text is being used as a placeholder for real text that is normally present. Sample text helps you understand how real text may look on your website.
All Ordered Lists
  1. Sample text is being used as a placeholder for real text that is normally present.
  2. Sample text is being used as a placeholder for real text that is normally present.
  3. Sample text is being used as a placeholder for real text that is normally present.
All Unordered Lists
  • Sample text is being used as a placeholder for real text that is normally present.
  • Sample text is being used as a placeholder for real text that is normally present.
  • Sample text is being used as a placeholder for real text that is normally present.

Text Classes

Text classes when typography style doesn't match the default HTML tag.

Text Sizes

text-size-large

Sample text is being used as a placeholder for real text that is normally present.

text-size-medium

Sample text is being used as a placeholder for real text that is normally present on your website.

text-size-regular

Sample text is being used as a placeholder for real text that is normally present. Sample text helps you understand how real text may look on your website.

text-size-small

Sample text is being used as a placeholder for real text that is normally present on your website. Sample text helps you understand how real text may look on your website.

text-size-tiny

Sample text is being used as a placeholder for real text that is normally present on your website. Sample text helps you understand how real text may look on your website.

Text Styles

text-style-strikethrough

text-style-strikethrough

text-style-italic

text-style-italic

text-style-muted

text-style-muted

text-style-allcaps

text-style-allcaps

text-style-nowrap

text-style-nowrap

text-style-link
text-style-quote

Sample text is being used as a placeholder.

text-style-2lines
This CSS style is not supported for Rich Texts on iOS.

Sample text is being used as a placeholder for real text that is normally present. Sample text helps you understand how real text may look on your website. Sample text is being used as a placeholder for real text text-style-2lines

text-style-3lines
This CSS style is not supported for Rich Texts on iOS.

Sample text is being used as a placeholder for real text that is normally present. Sample text helps you understand how real text may look on your website. Sample text is being used as a placeholder for real text. Sample text is being used as a placeholder for real text that is normally present. Sample text helps you understand how real text may look on your website. Sample text is being used as a placeholder for real text.

Text Weights

text-weight-xbold
text-weight-xbold
text-weight-bold
text-weight-bold
text-weight-semibold
text-weight-semibold
text-weight-medium
text-weight-medium
text-weight-normal
text-weight-normal
text-weight-light
text-weight-light

Text Alignments

text-align-left
text-align-left
text-align-center
text-align-center
text-align-right
text-align-right

Buttons

Button combo class system.

button
Button Text
button
is-small
Button Text
button
is-large
Button Text
button
is-secondary
Button Text
button
is-text
Button Text

Colors

Manage recurring text and background colors.

Text Colors

text-color-primary
text-color-primary
text-color-secondary
text-color-secondary
text-color-alternate
text-color-alternate

Background Colors

Primary

background-color-primary
background-color-secondary
background-color-tertiary
background-color-purple
background-color-maroon
background-color-tiffany
background-color-alternate

Max widths

Use the max-width CSS property to contain inner content to a maximum width.

max-width-full
max-width-full-tablet
max-width-full-mobile-portrait
max-width-full-mobile-landscape
max-width-xxlarge
max-width-xlarge
max-width-large
max-width-medium
max-width-small
max-width-xsmall
max-width-xxsmall

Paddings

Utility spacing system - padding classes. [padding-direction] + [padding-size].

Direction Classes

padding-bottom
padding-top
padding-vertical
padding-horizontal
padding-left
padding-right

Size Classes

padding-0
padding-tiny
padding-xxsmall
padding-xsmall
padding-small
padding-medium
padding-large
padding-xlarge
padding-xxlarge
padding-huge
padding-xhuge
padding-xxhuge
padding-custom1
padding-custom2
padding-custom3

Margins

Utility spacing system - padding classes. [margin-direction] + [margin-size].

Direction Classes

margin-bottom
margin-top
margin-vertical
margin-horizontal
margin-left
margin-right

Size Classes

margin-0
margin-tiny
margin-xxsmall
margin-xsmall
margin-small
margin-medium
margin-large
margin-xlarge
margin-xxlarge
margin-huge
margin-xhuge
margin-xxhuge
margin-custom1
margin-custom2
margin-custom3

Spacers

Unified spacer system for the project.

spacer-tiny
spacer-xxsmall
spacer-xsmall
spacer-small
spacer-medium
spacer-large
spacer-xlarge
spacer-xxlarge
spacer-huge
spacer-xhuge
spacer-xxhuge

Icons

Unify icons sizes. icon-height sets height of icons. icon-1x1 sets both height and width of icons.

icon-height-small
icon-height-medium
icon-height-large
icon-1x1-small
icon-1x1-medium
icon-1x1-large

tags / pills / badges / tokens

Unify icons sizes. icon-height sets height of icons. icon-1x1 sets both height and width of icons.

tag_component
Text Link
tag_component
is-purple
Text Link
tag_component
is-maroon
Text Link
tag_component
is-tiffany
Text Link

Useful utility systems

Utility classes we like to use in most of our projects to build faster.

hide
This element is hidden
hide-tablet
hide-mobile-portrait
hide-mobile-landscape
overflow-visible
overflow-hidden
overflow-auto
overflow-scroll
pointer-events-auto
pointer-events-none
layer
spacing-clean
align-center
z-index-1
z-index-2
inherit-color
aspect-ratio-square
aspect-ratio-portrait
aspect-ratio-landscape
aspect-ratio-widescreen

Useful Input fields

Utility classes we like to use in most of our projects to build faster.

☝️ How this works

The svg icon to the right is a native Webflow dropdown that opens on hover. I generally find these easier to work with that custom CSS or Webflow IX.

This is the description for this input
☝️ How this works

There's some optional CSS in here that styles the icon SVG when the input is focused.

Custom CSS
⌘K
https://
https://
Not a valid input
☝️ How this works
Custom CSS

There's some custom CSS in here that turns the input border color red, the svg red, and the help text red.

The styling will automatically apply to any input that has a parent with the class MS Error

Minimum of 8 characters.
☝️ How this works

This element uses Webflow's tab component to toggle between the "show" and "hide" states. The tabs and the input have attributes which tie into the custom code.

Add the following code to your page before the closing <body> tag.

I recommend copying the code on the published site to preserve line breaks.

<!--🟢 SHOW/HIDE PASSWORD CODE 🟢-->
<script>
//attach a click handler to the button to make it transform when clicked, via our transform() function below. Add right before your closing body tag.
document.querySelector("[data-transform]").addEventListener("click", transform);
//flag of whether or not it is a password field or text field
var isPassword = true;
//this function will toggle the input between being a password or a text input
function transform() {
   //copy the element itself, its html source, and value text to a variable
   var myInput = document.querySelector("[data-show]");
   var oldHtml = myInput.outerHTML;
   var text = myInput.value;
   if (isPassword) {
       //replace "password" with "text" in the html if it is a password field
       var newHtml = oldHtml.replace(/password/g, "text");
   } else {
       //replace "text" with "password" if it is a text field
       newHtml = oldHtml.replace(/text/g, "password");
   }
   //update the html
   myInput.outerHTML = newHtml;
   //restore the text value
   myInput = document.querySelector("[data-show]");
   myInput.value = text;
   //toggle the isPassword flag
   isPassword = !isPassword;
}
</script>

☝️ How this works
Step 1 - Code

Below is some custom javascript that you should add before the closing <body> tag.

CUSTOM JS
<!--🟢 COPY BUTTON CODE 🟢-->
<script>
const copyBtns = document.querySelectorAll('[data-copy-button]');copyBtns.forEach(copyBtn => {
 const inputId = copyBtn.getAttribute('data-copy-button');
 const input = document.querySelector(`[data-input="${inputId}"]`);  copyBtn.addEventListener('click', async () => {
   try {
     await navigator.clipboard.writeText(input.value);
     console.log('Text copied to clipboard');
     
     // Change button text to "Copied" and add class "success" for 3 seconds
     const originalBtnText = copyBtn.innerHTML;
     copyBtn.innerHTML = 'Copied';
     copyBtn.classList.add('is-success');
     setTimeout(() => {
       copyBtn.innerHTML = originalBtnText;
       copyBtn.classList.remove('is-success');
     }, 3000);
     
   } catch (err) {
     console.error('Failed to copy text: ', err);
   }
 });
});
</script>

Step 2 - Attributes

Make sure your input and your copy button have attributes that look like data-input="INPUT_NAME" and data-copy-button="INPUT_NAME".

The "INPUT_NAME" is something that you pick. As long as the button and input match each other you should be fine.

Step 3 - Multiple inputs

If you have multiple input/button pairs on the same page be sure to change the "INPUT_NAME" so that each pair is unique.

Step 4 - Styling

When the copy button is clicked, a class of is-success is added for 3 seconds. You can style it below.

☝️ How this works

This element uses a transparent input in conjunction with a series of "fake" input boxes in the background.

The CSS below is what applies styling to the "fake" input's in the background.

CUSTOM CSS

Here's a quick video that explains the feature in greater detail.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Useful radio fields

Utility classes we like to use in most of our projects to build faster.

This is optional description text
This is optional description text
This is optional description text
This is optional description text
☝️ How this works
Custom CSS

Each of these radio groups has some Custom CSS. You only need one per page, but I included one in each to make it easy for you copy and paste.

And each group of radio buttons has a unique name. The value is what gets saved/submitted.

If you're using Memberstack, each radio input has a data-ms-member attribute. You'll need one custom field per radio group.

Radio Rows
Select an Option w/ Description
☝️ How this works

These are default Webflow radio buttons. I'm using custom CSS to change the label styles when checked.

Custom CSS
Custom CSS
Custom CSS
This is optional description text
☝️ How this works
Custom CSS

The images are background images. Give each MS Radio Image it's own combo class so your images don't override each other.

Each of these radio groups has some Custom CSS. You only need one per page, but I included one in each to make it easy for you copy and paste.

And each group of radio buttons has a unique name. The value is what gets saved/submitted.

If you're using Memberstack, each radio input has a data-ms-member attribute. You'll need one custom field per radio group.

Only one option can be selected at a time.
☝️ How this works
Custom CSS

These are mostly Webflow elements which are lightly styled with custom CSS. I tried to keep as much in Webflow as possible.

Custom CSS
Custom CSS
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Useful checkbox fields

Utility classes we like to use in most of our projects to build faster.

☝️ How this works

This is the default Webflow Checkbox with a bunch of sibling elements. The label is positioned on top so that users can click anywhere to toggle it.

Use the following CSS to change the "Checked" styling.

Custom CSS
☝️ How this works

This is very similar to the above element with some additional classes to avoid conflicts.

Custom CSS
☝️ How this works
Custom CSS

These are mostly Webflow elements which are lightly styled with custom CSS. I tried to keep as much in Webflow as possible.

This is optional description text
This is optional description text
☝️ How this works

These are default Webflow checkbox. I'm using custom CSS to change the label styles when checked.

Custom CSS
☝️ How this works

These are default Webflow checkbox. I'm using custom CSS to change the label styles when checked.

There's an SVG embed inside of each checkbox. It's only visible if the checkbox is checked.

Custom CSS
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Useful select fields

Utility classes we like to use in most of our projects to build faster.

☝️ How this works

It's a native Webflow select field with a custom dropdown icon.

You can edit the dropdown SVG by selecting the input and then hit the right arrow key.

The CSS for the icon is below.

CUSTOM CSS
Generate a Select Input →

It's annoying to manually change the select options, so I made a tool which can do it automatically https://select-input-tool.webflow.io/

☝️ How this works
Step 1

Below is some custom CSS that you need to add to the page <header> code.

CUSTOM CSS
Step 2

You'll want to add the class name nice-select to any select input you want styled.

Step 3

Add the following code to your page before the closing <body> tag.

I recommend copying the code on the published site to preserve line breaks.

<!--🟢 CUSTOM SELECT CODE 🟢-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-nice-select/1.1.0/js/jquery.nice-select.min.js"></script>
<script>
$(document).ready(function() {
  $('.nice-select').niceSelect();
});
</script>

Credits

I originally discovered this component thanks to Noah Raskin on the Webflow Showcase.

☝️ How this works
Step 1

Below is some custom CSS that you need to add to the page <header> code.

CUSTOM CSS
Step 2

Add the following code to your page before the closing <body> tag.

I recommend copying the code on the published site to preserve line breaks.

<!--🟢 DATE PICKER CODE 🟢-->
<script src="https://fengyuanchen.github.io/datepicker/js/datepicker.js"></script>
<script>
   $(document).ready(function () {
       $('[data-input="datepicker"]').datepicker({
           format: 'mm-dd-yyyy'
       });
       // Available date placeholders:
       // Year: yyyy
       // Month: mm
       // Day: dd
   });
</script>

Credits

I discovered this code on the Flowbase blog.

☝️ How this works
Step 1

Add the following code to your page before the closing <body> tag.

I recommend copying the code on the published site to preserve line breaks.

<!--🟢 COLOR PICKER CODE 🟢-->
<script src="https://cdn.jsdelivr.net/npm/@jaames/iro/dist/iro.min.js"></script>
<script>
   // Create a new color picker instance
   // https://iro.js.org/guide.html#getting-started
   var colorPicker = new iro.ColorPicker(".ms-colorpicker", {
       // color picker options
       // Option guide: https://iro.js.org/guide.html#color-picker-options
       width: 180,
       color: "rgb(255, 0, 0)",
       borderWidth: 5,
       borderColor: "#f5f5f5",
   });    var values = document.getElementById("values");
   var hexInput = document.getElementById("hexInput");
   var swatch = document.getElementById("colorSwatch");    // https://iro.js.org/guide.html#color-picker-events
   colorPicker.on(["color:init", "color:change"], function(color){
       // Show the current color in different formats
       // Using the selected color: https://iro.js.org/guide.html#selected-color-api
       values.innerHTML = [
           "hex: " + color.hexString,
           "rgb: " + color.rgbString,
           "hsl: " + color.hslString,
       ].join("<br>");
       
       hexInput.value = color.hexString;
       swatch.style.backgroundColor = color.hexString;
   });    hexInput.addEventListener('change', function() {
       colorPicker.color.hexString = this.value;
       swatch.style.backgroundColor = this.value;
   });
</script>

Credits

Iro.js is color picker widget for JavaScript with a modern SVG-based user interface. No jQuery or extra CSS / images.

Head to iro.js.org for full documentation and features, or check out the source code on GitHub!

I discovered this package thanks for James Daniel on Codepen.

Custom Multi-Select Fields

All of the solutions below rely on a native Memberstack feature called "Checkbox Groups". You can learn more about how they work in in Memberstack documentation.

Custom Dropdown w/ Checkboxes & Webflow IX
Select all that apply
Custom Multi-select Input
Custom Multi-select + Custom Instant Search
Multi-select Buttons
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Useful rich text fields

Utility classes we like to use in most of our projects to build faster.

Please note the rich text editor is provided through Quill JS.  Follow their documentation to make edits.
☝️ How this works

There's a lot going on with this one... let's let Julian explain 🎉

Clone the Original Project
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Drag and Drop

Utility classes we like to use in most of our projects to build faster.

Option A
🟢
Option B
🟡
Option C
🔴
You'll probably want to hide and/or disable it in production. I'll add some HTML that you could use.
👈 How this works
Step 1

Duplicate the boxes to add more options. Be sure to keep the attributes and class names the same. MS Box and MS Boxes are required class names.

Step 2

Add the following code to the header of your page or site.

<style>
[draggable] {
 user-select: none;
}
[data-value] {
pointer-events: none;
}
</style>

Step 3

Next up, you can change the styling of boxes which are about to "replaced."

Style me
Step 4

If you want to use a hidden/disabled input then you can add the following code to an embed in Webflow. You can change NAME to be anything you like.

<input type="hidden" data-input="drag-order" maxlength="256" name="NAME" data-name="NAME" id="NAME" data-ms-member="FIELD_ID" required="">

The data-ms-member part is only required if you're using Memberstack.

Step 5

Last, and most importantly, you need to add the following code before the closing </body> tag.

<!--🟢 DRAG N DROP 🟢-->
<script>
document.addEventListener('DOMContentLoaded', (event) => {  var dragSrcEl = null;
 
 function handleDragStart(e) {
   this.style.opacity = '0.4';
   
   dragSrcEl = this;    e.dataTransfer.effectAllowed = 'move';
   e.dataTransfer.setData('text/html', this.innerHTML);
 }  function handleDragOver(e) {
   if (e.preventDefault) {
     e.preventDefault();
   }    e.dataTransfer.dropEffect = 'move';
   
   return false;
 }  function handleDragEnter(e) {
   this.classList.add('over');
 }  function handleDragLeave(e) {
   this.classList.remove('over');
 }  function handleDrop(e) {
   if (e.stopPropagation) {
     e.stopPropagation(); // stops the browser from redirecting.
   }
   
   if (dragSrcEl != this) {
     dragSrcEl.innerHTML = this.innerHTML;
     this.innerHTML = e.dataTransfer.getData('text/html');
   }
   
   let orderedBoxes = document.querySelectorAll('.ms-box div[data-value="true"]');    let orderList = Array.from(orderedBoxes).map(function(box) {
     return box.innerHTML;
   }).join(',');    let input = document.querySelector('input[data-input="drag-order"]');    input.value = orderList;    return false;
 }  function handleDragEnd(e) {
   this.style.opacity = '1';
   
   items.forEach(function (item) {
     item.classList.remove('over');
   });
 }
 
 let items = document.querySelectorAll('.ms-boxes .ms-box');
 items.forEach(function(item) {
   item.addEventListener('dragstart', handleDragStart, false);
   item.addEventListener('dragenter', handleDragEnter, false);
   item.addEventListener('dragover', handleDragOver, false);
   item.addEventListener('dragleave', handleDragLeave, false);
   item.addEventListener('drop', handleDrop, false);
   item.addEventListener('dragend', handleDragEnd, false);
 });  // Set initial value of the input field
 let orderedBoxes = document.querySelectorAll('.ms-box div[data-value="true"]');
 let orderList = Array.from(orderedBoxes).map(function(box) {
   return box.innerHTML;
 }).join(',');
 let input = document.querySelector('input[data-input="drag-order"]');
 input.value = orderList;
 
});
</script>

Credits

ChatGPT and this article on WebDev

This input type can work with Memberstack too.

You'll need to update the code, so I recommend you clone this other project and watch this video instead of following the instructions to the left.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Range Sliders

Utility classes we like to use in most of our projects to build faster.

0
0
👈 How this works
Step 1

Be sure to keep all the classnames, or update them in your code. They are required for this input to function.

Step 2

Add the following CSS to your page or site settings. Place the on the page to preview changes

CUSTOM CSS
Step 3

Change the styling of these elements right in Webflow. To style the handle and hover states edit the custom CSS.

0
Step 4 - Option A

Last, and most importantly, you need to add the following code before the closing </body> tag.

<!--🟢 RANGE SLIDERS 🟢-->
<script>
function rangeSlider() {
 var sliders = document.querySelectorAll('.ms-range-slider');  sliders.forEach(function(slider) {
   var range = slider.querySelector('.ms-range-slider-bar'),
       value = slider.querySelector('.ms-range-slider-value');    value.innerHTML = range.value;    range.addEventListener('input', function() {
     value.innerHTML = this.value;
   });
 });
}rangeSlider();
</script>

Step 4 - Option B

If you want to use this feature with Memberstack you'll want to use this code instead. You only need one or the other.

<!--🟢 RANGE SLIDERS W/ MEMBERSTACK 🟢-->
<script>
function rangeSlider() {
 var sliders = document.querySelectorAll('.ms-range-slider');  sliders.forEach(function(slider) {
   var range = slider.querySelector('.ms-range-slider-bar'),
       value = slider.querySelector('.ms-range-slider-value');    value.innerHTML = range.value;    range.addEventListener('input', function() {
     value.innerHTML = this.value;
   });
 });
}// Check if Memberstack is available
if (typeof window.$memberstackDom !== 'undefined') {
 // Get the current Memberstack member
 window.$memberstackDom.getCurrentMember().then(({ data: member }) => {
   if (member) {
     let id = member.id;
     // Memberstack member found, initialize range sliders
     rangeSlider();
   } else {
     // Memberstack member not found, initialize range sliders
     rangeSlider();
   }
 });
} else {
 // Memberstack not available, initialize range sliders
 rangeSlider();
}
</script>

Credits

The Simple Range Slider project by Adam Whitten

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Webflow elements

Native Webflow elements with Client-First classes applied.

form_component

Example of a form component using Folders

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
text-rich-text

Heading 1

Heading 2

Heading 3

Heading 4

Heading 5
Heading 6

Sample text with a link is being used as a placeholder for real text that is normally present. Sample text helps you understand how real text may look on your website. Sample text is being used as a placeholder for real text. Sample text is being used as a placeholder for real text. Sample text is being used as a placeholder for real text.

  • Sample text is being used as a placeholder for real text that is normally present.
  • Sample text is being used as a placeholder for real text that is normally present.
  • Sample text is being used as a placeholder for real text that is normally present.
  1. Sample text is being used as a placeholder for real text that is normally present.
  2. Sample text is being used as a placeholder for real text that is normally present.
  3. Sample text is being used as a placeholder for real text that is normally present.
Sample text is being used as a placeholder for real text that is normally present. Sample text helps you understand how real text may look on your website. Sample text is being used as a placeholder for real text that is normally present.
full-pricing-features_rich-text

10 free then 2p each

nav_component