Installation

.container {position: relative; height: 50vh;} .loader { position: absolute; top:40%; right: 50%; z-index: -1; width: 40px; height: 40px; border: 4px solid #f3f3f3; border-top: 4px solid var(–wp–preset–color–contrast); border-radius: 50%; animation: spin 1s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } .booking-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin-bottom: 20px; } .card { background: white; border-radius: 8px; padding: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .card-title { font-size: 1.25rem; font-weight: 600; margin-bottom: 15px; } .calendar-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; } .calendar-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; text-align: center; } .calendar-day { padding: 8px; cursor: pointer; border-radius: 50%; transition: background-color 0.2s; } .calendar-day:hover:not(.disabled) { background-color: #f0f0f0; } .calendar-day.selected { background-color: #166534; color: white; } .calendar-day.disabled { color: #ccc; cursor: not-allowed; } .calendar-day.today { background-color: #166534; color: white; } .weekday { font-weight: 500; font-size: 0.875rem; padding: 8px; color: #666; } .time-slot { width: 100%; padding: 10px; margin-bottom: 10px; border: 1px solid #e5e5e5; border-radius: 4px; background: none; cursor: pointer; transition: all 0.2s; } .time-slot:hover { background-color: #f0f0f0; } .time-slot.selected { background-color: #166534; color: white; border-color: #166534; } .form-container { max-width: 600px; margin: 0 auto; } .form-group { margin-bottom: 15px; } .form-group label { display: block; margin-bottom: 5px; font-weight: 500; } .form-control { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 1rem; } .interests-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin-top: 10px; } .button { background-color: #166534; color: white; padding: 12px 20px; border: none; border-radius: 4px; cursor: pointer; width: 100%; font-size: 1rem; transition: background-color 0.2s; } .button:hover { background-color: #145129; } .back-button { display: flex; align-items: center; gap: 5px; background: none; border: none; color: #166534; cursor: pointer; margin-bottom: 15px; font-size: 0.875rem; } .confirmation-details { background-color: #f0fdf4; padding: 15px; border-radius: 4px; margin-bottom: 20px; } .hidden { display: none; /* Initial state */ } .visible { display: block; opacity: 0; visibility: hidden; transition: opacity 0.5s, visibility 0.5s; } .visible.show { opacity: 1; visibility: visible; }

Free Estimate – Austin

60 Mins

Free onsite estimate with one of Southern Turf Co.’s expert Turf Advisors.

let currentDate = new Date(2025, 0); // January 2025 let selectedDate = null; let selectedTime = null; const interests = [ “Artificial Hedging”, “Looking great all year round”, “Low Maintenance”, “No more mud”, “For the dogs”, “A play area for the kids”, “Sports Field”, “I am interested in a putting/chipping green”, “Turf for my business”, “None of the above” ]; const times = [“10:00 AM”, “11:00 AM”, “12:00 PM”, “1:00 PM”, “2:00 PM”]; function initializeApp() { updateCalendar(); updateTimeSlots(); populateInterests(); } function updateCalendar() { const monthNames = [“January”, “February”, “March”, “April”, “May”, “June”, “July”, “August”, “September”, “October”, “November”, “December”]; document.getElementById(‘currentMonth’).textContent = `${monthNames[currentDate.getMonth()]} ${currentDate.getFullYear()}`; const calendar = document.getElementById(‘calendar’); calendar.innerHTML = ”; // Add weekday headers [‘Sun’, ‘Mon’, ‘Tue’, ‘Wed’, ‘Thu’, ‘Fri’, ‘Sat’].forEach(day => { const dayEl = document.createElement(‘div’); dayEl.className = ‘weekday’; dayEl.textContent = day; calendar.appendChild(dayEl); }); const firstDay = new Date(currentDate.getFullYear(), currentDate.getMonth(), 1); const lastDay = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0); // Add empty cells for days before first of month for (let i = 0; i < firstDay.getDay(); i++) { calendar.appendChild(document.createElement('div')); } // Add days of month for (let date = 1; date <= lastDay.getDate(); date++) { const dayEl = document.createElement('div'); dayEl.className = 'calendar-day'; dayEl.textContent = date; const currentDayDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), date); const isWeekend = currentDayDate.getDay() === 0 || currentDayDate.getDay() === 6; const isPast = currentDayDate selectDate(currentDayDate); } if (isToday) { dayEl.classList.add(‘disabled’); } if (selectedDate && currentDayDate.toDateString() === selectedDate.toDateString()) { dayEl.classList.add(‘selected’); } calendar.appendChild(dayEl); } } function selectDate(date) { selectedDate = date; updateCalendar(); updateTimeSlots(); document.getElementById(‘selectedDateDisplay’).textContent = `Selected: ${date.toLocaleDateString(‘en-US’, { weekday: ‘short’, month: ‘short’, day: ‘numeric’, year: ‘numeric’ })}`; } function updateTimeSlots() { const timeSlotsContainer = document.getElementById(‘timeSlots’); timeSlotsContainer.innerHTML = selectedDate ? times.map(time => ` `).join(”) : ‘

Please select a date first

‘; } function selectTime(time) { selectedTime = time; updateTimeSlots(); goToStep(2); } function changeMonth(delta) { currentDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + delta); updateCalendar(); } function populateInterests() { const interestsContainer = document.getElementById(‘interests’); interestsContainer.innerHTML = interests.map(interest => ` `).join(”); } function goToStep(step) { [‘bookingStep’, ‘formStep’, ‘confirmationStep’].forEach(id => { document.getElementById(id).classList.add(‘hidden’); }); const stepElement = document.getElementById( step === 1 ? ‘bookingStep’ : step === 2 ? ‘formStep’ : ‘confirmationStep’ ); setTimeout(() => { stepElement.classList.remove(‘hidden’); stepElement.classList.add(‘ visible show’); document.getElementById(‘container’).style.height = ‘initial’; }, 500); // Match the transition duration if (step === 2) { document.getElementById(‘appointmentDetails’).textContent = `${selectedDate.toLocaleDateString(‘en-US’, { weekday: ‘short’, month: ‘short’, day: ‘numeric’, year: ‘numeric’ })} | ${selectedTime}`; } } function handleSubmit(event) { event.preventDefault(); const form = event.target; const formData = { fullName: form.querySelector(‘input[placeholder=”Full Name”]’).value, email: form.querySelector(‘input[placeholder=”Email”]’).value, phone: form.querySelector(‘input[placeholder=”Phone”]’).value, address: form.querySelector(‘input[placeholder=”Street Address”]’).value, city: form.querySelector(‘input[placeholder=”City”]’).value, state: form.querySelector(‘input[placeholder=”State”]’).value, zipCode: form.querySelector(‘input[placeholder=”Zip Code”]’).value, squareFootage: form.querySelector(‘input[type=”number”]’).value, referralSource: form.querySelector(‘input[type=”text”]:last-of-type’).value, interests: Array.from(form.querySelectorAll(‘#interests input[type=”checkbox”]:checked’)) .map(checkbox => checkbox.value) }; // Display confirmation document.getElementById(‘confirmedDateTime’).innerHTML = `

Date: ${selectedDate.toLocaleDateString(‘en-US’, { weekday: ‘short’, month: ‘short’, day: ‘numeric’, year: ‘numeric’ })}

Time: ${selectedTime}

`; document.getElementById(‘confirmedDetails’).innerHTML = `

Contact Information

${formData.fullName}

${formData.email}

${formData.phone}

Property Details

${formData.address}

${formData.city}, ${formData.state} ${formData.zipCode}

Square Footage: ${formData.squareFootage}

${formData.interests.length ? `

Areas of Interest

    ${formData.interests.map(interest => `
  • • ${interest}
  • `).join(”)}
` : ”} ${formData.referralSource ? `

Referral Source

${formData.referralSource}

` : ”} `; // Move to confirmation step goToStep(3); // Here you would typically send the data to your server console.log(‘Form submitted with data:’, { appointmentDate: selectedDate, appointmentTime: selectedTime, …formData }); } // Form validation function setupFormValidation() { const form = document.getElementById(‘bookingForm’); const inputs = form.querySelectorAll(‘input[required]’); inputs.forEach(input => { input.addEventListener(‘invalid’, function(e) { e.preventDefault(); input.classList.add(‘invalid’); }); input.addEventListener(‘input’, function() { if (input.validity.valid) { input.classList.remove(‘invalid’); } }); }); } // Enhanced time slot hover effect function setupTimeSlotHover() { const timeSlots = document.querySelectorAll(‘.time-slot’); timeSlots.forEach(slot => { slot.addEventListener(‘mouseover’, function() { if (!this.classList.contains(‘selected’)) { this.style.transform = ‘scale(1.02)’; } }); slot.addEventListener(‘mouseout’, function() { this.style.transform = ‘scale(1)’; }); }); } // Initialize all functionality window.onload = function() { initializeApp(); setupFormValidation(); setupTimeSlotHover(); // Add validation styles const style = document.createElement(‘style’); style.textContent = ` .invalid { border-color: #dc2626 !important; } .invalid:focus { outline-color: #dc2626 !important; box-shadow: 0 0 0 2px rgba(220, 38, 38, 0.1); } @keyframes shake { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-5px); } 75% { transform: translateX(5px); } } .invalid { animation: shake 0.3s; } `; document.head.appendChild(style); };
  • Residential

    The Ultimate Guide to Residential Artificial Grass Installation (2025) A comprehensive resource for homeowners considering synthetic turf installation Introduction Artificial grass installation has revolutionized residential landscaping, offering a sustainable, low-maintenance alternative to natural lawns. This comprehensive guide covers everything you need to know about installing synthetic turf at your home, from initial planning to long-term…

  • Commercial

  • Playgrounds

  • Sports Fields

  • Balconies

  • Swimming Pools

    Artificial Grass for swimming pool deck

  • Rooftops

    Exclusive installation on rooftops to make it elegant

  • Putting Green 

  • Pavers

.container {position: relative; height: 50vh;} .loader { position: absolute; top:40%; right: 50%; z-index: -1; width: 40px; height: 40px; border: 4px solid #f3f3f3; border-top: 4px solid var(–wp–preset–color–contrast); border-radius: 50%; animation: spin 1s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } .booking-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin-bottom: 20px; } .card { background: white; border-radius: 8px; padding: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .card-title { font-size: 1.25rem; font-weight: 600; margin-bottom: 15px; } .calendar-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; } .calendar-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; text-align: center; } .calendar-day { padding: 8px; cursor: pointer; border-radius: 50%; transition: background-color 0.2s; } .calendar-day:hover:not(.disabled) { background-color: #f0f0f0; } .calendar-day.selected { background-color: #166534; color: white; } .calendar-day.disabled { color: #ccc; cursor: not-allowed; } .calendar-day.today { background-color: #166534; color: white; } .weekday { font-weight: 500; font-size: 0.875rem; padding: 8px; color: #666; } .time-slot { width: 100%; padding: 10px; margin-bottom: 10px; border: 1px solid #e5e5e5; border-radius: 4px; background: none; cursor: pointer; transition: all 0.2s; } .time-slot:hover { background-color: #f0f0f0; } .time-slot.selected { background-color: #166534; color: white; border-color: #166534; } .form-container { max-width: 600px; margin: 0 auto; } .form-group { margin-bottom: 15px; } .form-group label { display: block; margin-bottom: 5px; font-weight: 500; } .form-control { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 1rem; } .interests-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin-top: 10px; } .button { background-color: #166534; color: white; padding: 12px 20px; border: none; border-radius: 4px; cursor: pointer; width: 100%; font-size: 1rem; transition: background-color 0.2s; } .button:hover { background-color: #145129; } .back-button { display: flex; align-items: center; gap: 5px; background: none; border: none; color: #166534; cursor: pointer; margin-bottom: 15px; font-size: 0.875rem; } .confirmation-details { background-color: #f0fdf4; padding: 15px; border-radius: 4px; margin-bottom: 20px; } .hidden { display: none; /* Initial state */ } .visible { display: block; opacity: 0; visibility: hidden; transition: opacity 0.5s, visibility 0.5s; } .visible.show { opacity: 1; visibility: visible; }

Free Estimate – Austin

60 Mins

Free onsite estimate with one of Southern Turf Co.’s expert Turf Advisors.

let currentDate = new Date(2025, 0); // January 2025 let selectedDate = null; let selectedTime = null; const interests = [ “Artificial Hedging”, “Looking great all year round”, “Low Maintenance”, “No more mud”, “For the dogs”, “A play area for the kids”, “Sports Field”, “I am interested in a putting/chipping green”, “Turf for my business”, “None of the above” ]; const times = [“10:00 AM”, “11:00 AM”, “12:00 PM”, “1:00 PM”, “2:00 PM”]; function initializeApp() { updateCalendar(); updateTimeSlots(); populateInterests(); } function updateCalendar() { const monthNames = [“January”, “February”, “March”, “April”, “May”, “June”, “July”, “August”, “September”, “October”, “November”, “December”]; document.getElementById(‘currentMonth’).textContent = `${monthNames[currentDate.getMonth()]} ${currentDate.getFullYear()}`; const calendar = document.getElementById(‘calendar’); calendar.innerHTML = ”; // Add weekday headers [‘Sun’, ‘Mon’, ‘Tue’, ‘Wed’, ‘Thu’, ‘Fri’, ‘Sat’].forEach(day => { const dayEl = document.createElement(‘div’); dayEl.className = ‘weekday’; dayEl.textContent = day; calendar.appendChild(dayEl); }); const firstDay = new Date(currentDate.getFullYear(), currentDate.getMonth(), 1); const lastDay = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0); // Add empty cells for days before first of month for (let i = 0; i < firstDay.getDay(); i++) { calendar.appendChild(document.createElement('div')); } // Add days of month for (let date = 1; date <= lastDay.getDate(); date++) { const dayEl = document.createElement('div'); dayEl.className = 'calendar-day'; dayEl.textContent = date; const currentDayDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), date); const isWeekend = currentDayDate.getDay() === 0 || currentDayDate.getDay() === 6; const isPast = currentDayDate selectDate(currentDayDate); } if (isToday) { dayEl.classList.add(‘disabled’); } if (selectedDate && currentDayDate.toDateString() === selectedDate.toDateString()) { dayEl.classList.add(‘selected’); } calendar.appendChild(dayEl); } } function selectDate(date) { selectedDate = date; updateCalendar(); updateTimeSlots(); document.getElementById(‘selectedDateDisplay’).textContent = `Selected: ${date.toLocaleDateString(‘en-US’, { weekday: ‘short’, month: ‘short’, day: ‘numeric’, year: ‘numeric’ })}`; } function updateTimeSlots() { const timeSlotsContainer = document.getElementById(‘timeSlots’); timeSlotsContainer.innerHTML = selectedDate ? times.map(time => ` `).join(”) : ‘

Please select a date first

‘; } function selectTime(time) { selectedTime = time; updateTimeSlots(); goToStep(2); } function changeMonth(delta) { currentDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + delta); updateCalendar(); } function populateInterests() { const interestsContainer = document.getElementById(‘interests’); interestsContainer.innerHTML = interests.map(interest => ` `).join(”); } function goToStep(step) { [‘bookingStep’, ‘formStep’, ‘confirmationStep’].forEach(id => { document.getElementById(id).classList.add(‘hidden’); }); const stepElement = document.getElementById( step === 1 ? ‘bookingStep’ : step === 2 ? ‘formStep’ : ‘confirmationStep’ ); setTimeout(() => { stepElement.classList.remove(‘hidden’); stepElement.classList.add(‘ visible show’); document.getElementById(‘container’).style.height = ‘initial’; }, 500); // Match the transition duration if (step === 2) { document.getElementById(‘appointmentDetails’).textContent = `${selectedDate.toLocaleDateString(‘en-US’, { weekday: ‘short’, month: ‘short’, day: ‘numeric’, year: ‘numeric’ })} | ${selectedTime}`; } } function handleSubmit(event) { event.preventDefault(); const form = event.target; const formData = { fullName: form.querySelector(‘input[placeholder=”Full Name”]’).value, email: form.querySelector(‘input[placeholder=”Email”]’).value, phone: form.querySelector(‘input[placeholder=”Phone”]’).value, address: form.querySelector(‘input[placeholder=”Street Address”]’).value, city: form.querySelector(‘input[placeholder=”City”]’).value, state: form.querySelector(‘input[placeholder=”State”]’).value, zipCode: form.querySelector(‘input[placeholder=”Zip Code”]’).value, squareFootage: form.querySelector(‘input[type=”number”]’).value, referralSource: form.querySelector(‘input[type=”text”]:last-of-type’).value, interests: Array.from(form.querySelectorAll(‘#interests input[type=”checkbox”]:checked’)) .map(checkbox => checkbox.value) }; // Display confirmation document.getElementById(‘confirmedDateTime’).innerHTML = `

Date: ${selectedDate.toLocaleDateString(‘en-US’, { weekday: ‘short’, month: ‘short’, day: ‘numeric’, year: ‘numeric’ })}

Time: ${selectedTime}

`; document.getElementById(‘confirmedDetails’).innerHTML = `

Contact Information

${formData.fullName}

${formData.email}

${formData.phone}

Property Details

${formData.address}

${formData.city}, ${formData.state} ${formData.zipCode}

Square Footage: ${formData.squareFootage}

${formData.interests.length ? `

Areas of Interest

    ${formData.interests.map(interest => `
  • • ${interest}
  • `).join(”)}
` : ”} ${formData.referralSource ? `

Referral Source

${formData.referralSource}

` : ”} `; // Move to confirmation step goToStep(3); // Here you would typically send the data to your server console.log(‘Form submitted with data:’, { appointmentDate: selectedDate, appointmentTime: selectedTime, …formData }); } // Form validation function setupFormValidation() { const form = document.getElementById(‘bookingForm’); const inputs = form.querySelectorAll(‘input[required]’); inputs.forEach(input => { input.addEventListener(‘invalid’, function(e) { e.preventDefault(); input.classList.add(‘invalid’); }); input.addEventListener(‘input’, function() { if (input.validity.valid) { input.classList.remove(‘invalid’); } }); }); } // Enhanced time slot hover effect function setupTimeSlotHover() { const timeSlots = document.querySelectorAll(‘.time-slot’); timeSlots.forEach(slot => { slot.addEventListener(‘mouseover’, function() { if (!this.classList.contains(‘selected’)) { this.style.transform = ‘scale(1.02)’; } }); slot.addEventListener(‘mouseout’, function() { this.style.transform = ‘scale(1)’; }); }); } // Initialize all functionality window.onload = function() { initializeApp(); setupFormValidation(); setupTimeSlotHover(); // Add validation styles const style = document.createElement(‘style’); style.textContent = ` .invalid { border-color: #dc2626 !important; } .invalid:focus { outline-color: #dc2626 !important; box-shadow: 0 0 0 2px rgba(220, 38, 38, 0.1); } @keyframes shake { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-5px); } 75% { transform: translateX(5px); } } .invalid { animation: shake 0.3s; } `; document.head.appendChild(style); };