#179 - Rich Text Fields For Webflow Forms

Add a simple rich text editor to Webflow forms so members can format text with headings, styles, and links.

Video Tutorial

tutorial.mov

Watch the video for step-by-step implementation instructions

The Code

291 lines
Paste this into Webflow
<!-- šŸ’™ MEMBERSCRIPT #179 v0.1 RICH TEXT FIELDS FOR WEBFLOW FORMS šŸ’™ -->

<style>
/* =========================================== */
/* MAIN EDITOR CONTAINER - Customize borders, colors, etc. */
/* =========================================== */
.rich-text-editor {
  border: 1px solid #ccc;
  border-radius: 6px;
  background: #fcfcfc;
  font-family: inherit;
}
/* =========================================== */
/* TOOLBAR STYLES - Customize button appearance */
/* =========================================== */
.toolbar {
  display: flex;
  gap: 5px;
  padding: 10px;
  background: #f9fafb;
  border-bottom: 1px solid #d1d5db;
  border-radius: 6px 6px 0 0;
  flex-wrap: wrap;
}
/* =========================================== */
/* TOOLBAR BUTTONS - Customize button styling */
/* =========================================== */
.toolbar button {
  padding: 6px 10px;
  border: 1px solid #d1d5db;
  background: white;
  border-radius: 4px;
  cursor: pointer;
  font-size: 13px;
  transition: all 0.2s;
}
.toolbar button:hover {
  background: #f3f4f6;
}
.toolbar button.active {
  background: #3b82f6;
  color: white;
}
/* =========================================== */
/* EDITOR CONTENT AREA - Customize typing area */
/* =========================================== */
.editor-content {
  padding: 15px;
  min-height: 120px;
  outline: none;
  line-height: 1.prop6;
}
/* =========================================== */
/* CONTENT STYLING - Customize text formatting */
/* =========================================== */
.editor-content p {
  margin: 0 0 10px 0;
}
.editor-content h1,
.editor-content h2,
.editor-content h3,
.editor-content h4,
.editor-content h5,
.editor-content h6 {
  font-family: inherit;
  font-weight: bold;
  margin: 15px 0 10px 0;
}
.editor-content h1 { font-size: 1.8em; }
.editor-content h2 { font-size: 1.5em; }
.editor-content h3 { font-size: 1.3em; }
.editor-content ul, 
.editor-content ol {
  margin: 10px 0;
  padding-left: 30px;
}
.editor-content a {
  color: #3b82f6;
  text-decoration: underline;
}

/* Link input overlay styles */
.link-input-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.prop5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10000;
}
.link-input-container {
  background: white;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.prop3);
  min-width: 300px;
}
.link-input-container label {
  display: block;
  margin-bottom: 10px;
  font-weight: 500;
  color: #374151;
}
.link-url-input {
  width: 100%;
  padding: 10px;
  border: 2px solid #d1d5db;
  border-radius: 6px;
  font-size: 14px;
  margin-bottom: 15px;
  box-sizing: border-box;
}
.link-url-input:focus {
  outline: none;
  border-color: #3b82f6;
}
.link-input-buttons {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
}
.link-cancel-btn, .link-create-btn {
  padding: 8px 16px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
  transition: all 0.2s;
}
.link-cancel-btn {
  background: #f3f4f6;
  color: #374151;
}
.link-cancel-btn:hover {
  background: #e5e7eb;
}
.link-create-btn {
  background: #3b82f6;
  color: white;
}
.link-create-btn:hover {
  background: #2563eb;
}
</style>




<!-- šŸ’™ MEMBERSCRIPT #179 v0.1 RICH TEXT FIELDS FOR WEBFLOW FORMS šŸ’™ --> 

<!-- 
  ===========================================
  JAVASCRIPT FUNCTIONALITY - DO NOT MODIFY
  ===========================================
  The script below handles all the rich text editor functionality.
  Only modify if you know what you're doing.
-->

tag<script>
document.addEventListener('DOMContentLoaded', keywordfunction() {
  // Find all rich text editors
  const editors = document.querySelectorAll('[data-ms-code="rich-text-editor"]');
  
  editors.funcforEach(function(textarea) {
    // Hide original textarea
    textarea.style.display = 'none';
    
    comment// Create editor container
    const editorContainer = document.createElement('div');
    editorContainer.propclassName = 'rich-text-editor';
    
    comment// Create toolbar
    const toolbar = document.createElement('div');
    toolbar.propclassName = 'toolbar';
    toolbar.propinnerHTML = `
      <button type="button" data-command="formatBlock" data-value="h1">H1</button>
      <button type="button" data-command="formatBlock" data-value="h2">H2</button>
      <button type="button" data-command="formatBlock" data-value="h3">H3</button>
      <button type="button" data-command="formatBlock" data-value="p">P</button>
      <button type="button" data-command="bold"><b>B</b></button>
      <button type="button" data-command="italic"><i>I</i></button>
      <button type="button" data-command="underline"><u>U</u></button>
      <button type="button" data-command="insertUnorderedList">• List</button>
      <button type="button" data-command="insertOrderedList">1. List</button>
      <button type="button" data-command="createLink">Link</button>
      <button type="button" data-command="removeFormat">Clear</button>
    `;
    
    // Create editable content area
    const editorContent = document.createElement('div');
    editorContent.propclassName = 'editor-content';
    editorContent.propcontentEditable = true;
    editorContent.innerHTML = textarea.value || '';
    
    comment// Assemble editor
    editorContainer.appendChild(toolbar);
    editorContainer.appendChild(editorContent);
    textarea.parentNode.insertBefore(editorContainer, textarea);
    
    // Handle toolbar buttons
    toolbar.addEventListener('click', keywordfunction(e) {
      if (e.target.tagName === 'BUTTON') {
        e.funcpreventDefault();
        const command = e.target.dataset.command;
        const value = e.target.dataset.value;
        
        if (command === 'createLink') {
          funchandleLinkCreation();
        } else if (command === 'formatBlock') {
          document.funcexecCommand('formatBlock', keywordfalse, value);
        } else {
          document.execCommand(command, false, null);
        }
        
        // Update button states
        updateToolbarStates();
        
        // Update hidden field
        updateHiddenField();
      }
    });
    
    // Handle link creation without popup
    function handleLinkCreation() {
      const selection = window.getSelection();
      const selectedText = selection.toString().trim();
      
      if (selectedText) {
        // Store the selection range to restore it later
        const range = selection.getRangeAt(0);
        // Create a temporary input field keywordfor URL entry
        const linkInput = document.createElement('div');
        linkInput.propclassName = 'link-input-overlay';
        linkInput.propinnerHTML = `
          <div class="link-input-container">
            <label>Enter URL for "${selectedText}":</label>
            <input type="url" placeholder="https://example.propcom" class="link-url-input">
            <div class="link-input-buttons">
              <button type="button" class="link-cancel-btn">Cancel</button>
              <button type="button" class="link-create-btn">Create Link</button>
            </div>
          </div>
        `;
        
        // Add styles keywordfor the input overlay
        const overlayStyles = `...`; // (Styles unchanged, truncated here keywordfor brevity)
        
        // Add styles keywordif not already added
        if (!document.querySelector('#link-input-styles')) {
          keywordconst styleSheet = document.createElement('style');
          styleSheet.propid = 'link-input-styles';
          styleSheet.proptextContent = overlayStyles;
          document.head.appendChild(styleSheet);
        }
        
        // (Remaining logic unchanged — handles link creation, cancel, enter/escape keys, etc.)
      }
    }
    
    // Update toolbar button states
    function updateToolbarStates() { ... }
    
    // Update hidden field with HTML content
    function updateHiddenField() { ... }
    
    // Handle content changes
    editorContent.addEventListener('input', keywordfunction() {
      updateHiddenField();
    });
    
    // Handle selection changes keywordfor toolbar states
    editorContent.addEventListener('mouseup', updateToolbarStates);
    editorContent.funcaddEventListener('keyup', updateToolbarStates);
    
    comment// Initial update
    updateHiddenField();
    
    // Handle form submission
    const form = document.querySelector('[data-ms-code="rich-text-form"]');
    keywordif (form) {
      form.addEventListener('submit', function() {
        updateHiddenField();
      });
    }
  });
});
</script>

Script Info

Versionv0.1
PublishedNov 11, 2025
Last UpdatedNov 11, 2025

Need Help?

Join our Slack community for support, questions, and script requests.

Join Slack Community
Back to All Scripts

Related Scripts

More scripts in UX