All visual customizations in Next-Gen Knack should be handled with CSS using the official class names, not JavaScript DOM manipulation. This approach provides good performance, maintainability, and user experience.
COMING SOON
What You'll Learn
You'll learn the fundamental principle of Next-Gen Knack: separating presentation from logic. Learn how to use official CSS classes to create responsive interfaces while keeping JavaScript focused purely on business logic. This approach leads to more maintainable, performant applications that follow modern web development best practices.
Core Principle
JavaScript for Logic, CSS for Presentation
// ✅ Correct Approach
Knack.on('form:submit', ({ data, viewKey }) => {
// Business logic only
if (data.field_priority === 'High') {
console.log('High priority item created');
triggerUrgentWorkflow(data);
}
// Use CSS classes for visual feedback
// Prefer native CSS validation states:
// input[name="field_email"]:invalid { /* styles */ }
}
});
// ⚠️ Caution - DOM manipulation
Knack.on('form:submit', ({ data }) => {
document.querySelector('.button').style.backgroundColor = 'green';
document.querySelector('.status').innerHTML = 'Processing...';
});
Official Next-Gen CSS Classes
Next-Gen Knack provides a comprehensive set of CSS classes for targeting elements. See the CSS Implementation Guide for more information.
Tip: You can find the exact scene/view keys (e.g., #scene_123 #view_456
) from the Page Editor- open the page and view settings; the key is listed near the element name.
See a demo here.
Page and Scene Classes
.kn-page
- Page containers#scene_123
- Specific page by scene key.kn-page-title
- Page titles.kn-page-section
- Page sections
View Classes
.kn-view
- All view containers#scene_123 #view_456
- Specific view by scene and view key.kn-form-view
- Form views.kn-table-view
- Table views.kn-list-view
- List views.kn-details-view
- Detail views
Form Classes
.kn-form-view-column
- Form field containers.kn-action-button
- Submit and action buttons- Form inputs maintain their standard HTML attributes for targeting
Table Classes
.kn-table-view-wrapper
- Table container.kn-table-view
- Table element- Table cells can be targeted with attribute selectors
Button Customization
Use CSS for all button styling:
/* Style all action buttons (submit buttons) */
.kn-action-button {
background: linear-gradient(135deg, #007bff, #0056b3);
color: white;
border: none;
padding: 1rem 2rem;
border-radius: 8px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
}
.kn-action-button:hover {
transform: translateY(-2px);
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}
/* Style buttons in specific form views */
.kn-form-view .kn-action-button {
background: linear-gradient(135deg, #28a745, #1e7e34);
width: 100%;
padding: 1rem;
}
/* Target specific view using scene and view classes */
#scene_123 #view_456 .kn-action-button {
background-color: #17a2b8;
border-radius: 12px;
}
/* Change button text using pseudo-elements */
#scene_123 #view_456 .kn-action-button::before {
content: 'Create Contact';
}
#scene_123 #view_456 .kn-action-button span {
display: none; /* Hide original text */
}
JavaScript for business logic only:
Knack.ready().then(async () => {
// Use events for logic, not styling
Knack.on('form:submit:view_456', ({ data, viewKey }) => {
console.log('Contact form submitted:', data);
// Business logic based on form submission
if (data.field_company && data.field_company.includes('Enterprise')) {
console.log('Enterprise contact created, flagging for priority handling');
triggerEnterpriseWorkflow(data);
}
});
});
Form Styling and Enhancements
Use CSS for visual enhancements:
/* Style form views */
.kn-form-view {
background: white;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
padding: 3rem;
max-width: 600px;
margin: 0 auto;
}
.kn-form-view-column {
margin-bottom: 2rem;
}
/* Style specific form view */
#scene_123 #view_456.kn-form-view {
background-color: #e3f2fd;
border: 2px solid #2196f3;
}
/* Style form inputs */
.kn-form-view input,
.kn-form-view select,
.kn-form-view textarea {
border: 2px solid #e9ecef;
border-radius: 6px;
padding: 12px;
width: 100%;
transition: border-color 0.2s ease;
}
.kn-form-view input:focus,
.kn-form-view select:focus,
.kn-form-view textarea:focus {
border-color: #007bff;
outline: none;
box-shadow: 0 0 0 3px rgba(0,123,255,0.1);
}
/* Required field styling */
.kn-form-view input[required] {
border-left: 4px solid #dc3545;
}
.kn-form-view input[required] + label::after {
content: ' *';
color: #dc3545;
font-weight: bold;
}
/* Text transformation */
.kn-form-view input[name*="field_name"] {
text-transform: capitalize;
}
.kn-form-view input[type="tel"] {
font-family: 'Courier New', monospace;
letter-spacing: 1px;
}
JavaScript for data processing :
Knack.ready().then(async () => {
// Monitor field changes for business logic
Knack.on('form:field:change', ({ fieldKey, newValue, oldValue }) => {
// Process field changes for business logic
if (fieldKey === 'field_phone') {
console.log('Phone number changed:', newValue);
// Could validate format, trigger lookups, etc.
}
if (fieldKey === 'field_email') {
console.log('Email changed:', newValue);
// Business logic for email validation
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (newValue && !emailRegex.test(newValue)) {
console.warn('Invalid email format detected:', newValue);
// Add CSS class for styling feedback
document.body.classList.add('email-validation-error');
} else {
document.body.classList.remove('email-validation-error');
}
}
});
});
Table and List Customizations
Use CSS for visual indicators:
/* Style table views */
.kn-table-view-wrapper {
overflow-x: auto;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.kn-table-view {
width: 100%;
border-collapse: collapse;
background: white;
}
.kn-table-view th {
background: linear-gradient(135deg, #f8f9fa, #e9ecef);
color: #6c757d;
font-weight: 600;
padding: 1rem;
text-align: left;
border-bottom: 2px solid #dee2e6;
}
.kn-table-view td {
padding: 1rem;
border-bottom: 1px solid #f1f3f4;
transition: background-color 0.2s ease;
}
.kn-table-view tr:hover td {
background-color: #f8f9fa;
}
/* Status-based styling using attribute selectors */
.kn-table-view td[data-field="field_status"] {
font-weight: bold;
text-align: center;
border-radius: 4px;
}
/* Priority indicators using pseudo-elements */
.kn-table-view td[data-field="field_priority"][data-value="High"]::before {
content: '🔴 ';
}
.kn-table-view td[data-field="field_priority"][data-value="Medium"]::before {
content: '🟡 ';
}
.kn-table-view td[data-field="field_priority"][data-value="Low"]::before {
content: '🟢 ';
}
/* Target specific table view */
#scene_123 #view_456 .kn-table-view {
border: 2px solid #28a745;
}
#scene_123 #view_456 .kn-table-view th {
background-color: #28a745;
color: white;
}
JavaScript for data analysis :
Knack.ready().then(async () => {
// Use records render for data processing
Knack.on('records:render:view_188', ({ records, viewKey }) => {
console.log('Table data loaded:', records.length, 'records');
// Analyze data for business insights
const statusCounts = records.reduce((acc, record) => {
const status = record.field_status;
acc[status] = (acc[status] || 0) + 1;
return acc;
}, {});
console.log('Status distribution:', statusCounts);
// Could trigger alerts, reports, etc.
if (statusCounts.Expired > 10) {
console.log('High number of expired records detected');
triggerExpirationAlert();
}
// Priority analysis
const highPriorityCount = records.filter(r => r.field_priority === 'High').length;
if (highPriorityCount > 5) {
console.log('Multiple high priority items detected:', highPriorityCount);
triggerManagementAlert(highPriorityCount);
}
});
});
Card Container Styling
Use CSS for card layouts:
/* Style card containers */
.kn-card {
background: white;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
margin-bottom: 1rem;
}
.kn-card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 15px rgba(0, 0, 0, 0.15);
}
/* Style list view columns within cards */
.kn-list-view-column {
background: white;
border-radius: 8px;
padding: 1rem;
margin-bottom: 1rem;
transition: all 0.3s ease;
}
.kn-list-view-column:hover {
transform: translateY(-4px);
box-shadow: 0 8px 15px rgba(0, 0, 0, 0.15);
}
/* Style details view columns */
.kn-details-view-column {
margin-bottom: 1rem;
padding: 0.5rem 0;
}
/* Target cards in specific views */
#view_3 .kn-list-view-column {
background-color: #f8f9fa;
border: 1px solid #e9ecef;
}
#scene_123 .kn-card {
background-color: #fff;
border: 1px solid #007bff;
}
/* Card status indicators */
.kn-card[data-status="active"] {
border-left: 4px solid #28a745;
}
.kn-card[data-status="pending"] {
border-left: 4px solid #ffc107;
}
.kn-card[data-status="expired"] {
border-left: 4px solid #dc3545;
}