generated from xkeshav/astro-template
-
Notifications
You must be signed in to change notification settings - Fork 4
Open
Labels
enhancementNew feature or requestNew feature or request
Description
Printable Handwriting Practice Sheets
I'll create a printer-friendly handwriting practice page that allows users to generate worksheets for any alphabet (English or Hindi) with dashed guides for tracing. The solution will include SVG-based letters and print optimization.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Printable Handwriting Practice Sheets</title>
<link href="https://fonts.googleapis.com/css2?family=Schoolbell&display=swap" rel="stylesheet">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #e0f7fa 0%, #bbdefb 100%);
color: #2c3e50;
padding: 20px;
min-height: 100vh;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
header {
text-align: center;
padding: 30px 0;
background: rgba(255, 255, 255, 0.9);
border-radius: 15px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
margin-bottom: 30px;
}
h1 {
font-size: 2.8rem;
color: #2980b9;
margin-bottom: 15px;
}
.subtitle {
font-size: 1.4rem;
max-width: 800px;
margin: 0 auto 25px;
color: #34495e;
}
.controls {
background: white;
border-radius: 15px;
padding: 30px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
margin-bottom: 30px;
}
.input-group {
margin-bottom: 25px;
}
label {
display: block;
font-size: 1.2rem;
margin-bottom: 10px;
font-weight: 600;
color: #2c3e50;
}
input, select {
width: 100%;
padding: 15px;
font-size: 1.1rem;
border: 2px solid #3498db;
border-radius: 10px;
background: #f8f9fa;
}
button {
background: #3498db;
color: white;
border: none;
padding: 15px 30px;
font-size: 1.2rem;
border-radius: 50px;
cursor: pointer;
font-weight: 600;
transition: all 0.3s ease;
box-shadow: 0 4px 10px rgba(52, 152, 219, 0.4);
display: inline-flex;
align-items: center;
gap: 10px;
}
button:hover {
background: #2980b9;
transform: translateY(-3px);
box-shadow: 0 6px 15px rgba(52, 152, 219, 0.6);
}
button:active {
transform: translateY(1px);
}
.btn-group {
display: flex;
gap: 15px;
flex-wrap: wrap;
}
.print-btn {
background: #27ae60;
}
.print-btn:hover {
background: #219653;
}
.clear-btn {
background: #e74c3c;
}
.clear-btn:hover {
background: #c0392b;
}
.practice-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 30px;
margin-bottom: 40px;
}
.letter-card {
background: white;
border-radius: 15px;
overflow: hidden;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
transition: transform 0.3s ease;
}
.letter-card:hover {
transform: translateY(-10px);
}
.card-header {
background: #3498db;
color: white;
text-align: center;
padding: 15px;
font-size: 2.5rem;
font-weight: bold;
}
.hindi-letter {
font-family: 'Mangal', 'Nirmala UI', sans-serif;
font-size: 3.5rem;
}
.practice-area {
padding: 30px;
min-height: 300px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: #f8f9fa;
position: relative;
}
.letter-guide {
position: absolute;
width: 90%;
height: 90%;
border: 2px dashed #bdc3c7;
border-radius: 10px;
pointer-events: none;
}
.practice-btn {
background: #9b59b6;
width: 100%;
border-radius: 0;
padding: 15px;
justify-content: center;
}
.practice-btn:hover {
background: #8e44ad;
}
footer {
text-align: center;
padding: 30px;
background: rgba(255, 255, 255, 0.9);
border-radius: 15px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
font-size: 1.1rem;
color: #7f8c8d;
}
/* Print-specific styles */
@media print {
body {
background: white;
padding: 0;
}
header, .controls, .practice-btn, footer {
display: none;
}
.container {
max-width: 100%;
}
.practice-grid {
display: block;
}
.letter-card {
break-inside: avoid;
page-break-inside: avoid;
box-shadow: none;
margin-bottom: 20px;
}
.practice-area {
min-height: 800px;
}
}
@media (max-width: 768px) {
.practice-grid {
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
h1 {
font-size: 2.2rem;
}
.subtitle {
font-size: 1.1rem;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>✏️ Printable Handwriting Practice Sheets ✏️</h1>
<p class="subtitle">Create custom tracing worksheets for English and Hindi alphabets. Perfect for kids learning to write!</p>
</header>
<div class="controls">
<div class="input-group">
<label for="alphabetType">Select Alphabet Type:</label>
<select id="alphabetType">
<option value="english">English Alphabet</option>
<option value="hindi">Hindi Alphabet (हिंदी वर्णमाला)</option>
</select>
</div>
<div class="input-group">
<label for="lettersInput">Enter Letters to Practice (comma separated):</label>
<input type="text" id="lettersInput" placeholder="For example: A,B,C or अ,आ,इ">
</div>
<div class="btn-group">
<button id="generateBtn">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 0 1-9 9 9 9 0 0 1-9-9 9 9 0 0 1 9-9c2.4 0 4.7.8 6.5 2.3"/><path d="M16 8h4v4"/><path d="M16 2h6v6"/></svg>
Generate Practice Sheets
</button>
<button id="printAllBtn" class="print-btn">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 6 2 18 2 18 9"></polyline><path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"></path><rect x="6" y="14" width="12" height="8"></rect></svg>
Print All Sheets
</button>
<button id="clearBtn" class="clear-btn">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line></svg>
Clear Sheets
</button>
</div>
</div>
<div id="practiceGrid" class="practice-grid">
<!-- Practice sheets will be generated here -->
</div>
<footer>
<p>Made with ❤️ for kids learning to write | Print and practice as many times as you want!</p>
<p>Tip: For best results, use thick paper and a pencil with a good eraser.</p>
</footer>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const generateBtn = document.getElementById('generateBtn');
const printAllBtn = document.getElementById('printAllBtn');
const clearBtn = document.getElementById('clearBtn');
const lettersInput = document.getElementById('lettersInput');
const alphabetType = document.getElementById('alphabetType');
const practiceGrid = document.getElementById('practiceGrid');
// Sample data for letters
const englishLetters = {
'A': 'M50,170 L100,30 M100,30 L150,170 M65,110 L135,110',
'B': 'M50,30 Q90,30 100,70 Q100,100 70,110 Q100,120 100,150 Q90,190 50,190 L50,30',
'C': 'M150,50 Q120,30 90,30 Q50,50 50,100 Q50,150 90,170 Q120,190 150,170',
'D': 'M50,30 L50,170 Q70,190 100,190 Q130,190 150,170 Q150,50 100,30 Q70,30 50,50',
'E': 'M150,30 L50,30 L50,170 L150,170 M50,100 L120,100'
};
const hindiLetters = {
'अ': 'M100,50 Q50,70 50,120 Q60,170 100,170 Q140,170 150,120 Q140,70 100,50',
'आ': 'M100,50 Q50,70 50,120 Q60,170 100,170 Q140,170 150,120 Q140,70 100,50 M150,120 L180,170',
'इ': 'M100,50 Q50,70 50,120 Q60,170 100,170 Q140,170 150,120 Q140,70 100,50 M80,30 L120,30',
'ई': 'M100,50 Q50,70 50,120 Q60,170 100,170 Q140,170 150,120 Q140,70 100,50 M70,30 L130,30 M80,30 L120,30',
'उ': 'M100,50 Q50,70 50,120 Q60,170 100,170 Q140,170 150,120 Q140,70 100,50 M100,30 L100,50'
};
// Generate practice sheets
generateBtn.addEventListener('click', function() {
const letters = lettersInput.value.split(',').map(letter => letter.trim());
const type = alphabetType.value;
if (letters.length === 0 || (letters.length === 1 && letters[0] === '')) {
alert('Please enter at least one letter');
return;
}
practiceGrid.innerHTML = '';
letters.forEach(letter => {
if (letter) {
const letterData = (type === 'english') ? englishLetters[letter] : hindiLetters[letter];
createLetterCard(letter, type, letterData);
}
});
});
// Print all sheets
printAllBtn.addEventListener('click', function() {
window.print();
});
// Clear all sheets
clearBtn.addEventListener('click', function() {
practiceGrid.innerHTML = '';
lettersInput.value = '';
});
// Create individual letter card
function createLetterCard(letter, type, pathData) {
const card = document.createElement('div');
card.className = 'letter-card';
const header = document.createElement('div');
header.className = 'card-header';
header.textContent = letter;
if (type === 'hindi') {
header.classList.add('hindi-letter');
}
const practiceArea = document.createElement('div');
practiceArea.className = 'practice-area';
const guide = document.createElement('div');
guide.className = 'letter-guide';
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('viewBox', '0 0 200 200');
svg.setAttribute('width', '180');
svg.setAttribute('height', '180');
svg.style.margin = '20px 0';
// Create dashed path for tracing
if (pathData) {
const paths = pathData.split(' M ');
paths.forEach((path, i) => {
if (path) {
const pathElem = document.createElementNS('http://www.w3.org/2000/svg', 'path');
pathElem.setAttribute('d', `M ${path}`);
pathElem.setAttribute('fill', 'none');
pathElem.setAttribute('stroke', '#3498db');
pathElem.setAttribute('stroke-width', '3');
pathElem.setAttribute('stroke-dasharray', '8,5');
pathElem.setAttribute('stroke-linecap', 'round');
svg.appendChild(pathElem);
}
});
} else {
// If no path data, just display the letter
const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
text.setAttribute('x', '100');
text.setAttribute('y', '100');
text.setAttribute('text-anchor', 'middle');
text.setAttribute('dominant-baseline', 'middle');
text.setAttribute('font-size', '100');
text.setAttribute('fill', '#3498db');
text.textContent = letter;
svg.appendChild(text);
}
practiceArea.appendChild(guide);
practiceArea.appendChild(svg);
const practiceBtn = document.createElement('button');
practiceBtn.className = 'practice-btn print-btn';
practiceBtn.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 6 2 18 2 18 9"></polyline><path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"></path><rect x="6" y="14" width="12" height="8"></rect></svg>
Print Practice Sheet for ${letter}
`;
practiceBtn.addEventListener('click', function() {
// Create a print-friendly version of just this letter
const printWindow = window.open('', '_blank');
printWindow.document.write(`
<!DOCTYPE html>
<html>
<head>
<title>Practice ${letter}</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
text-align: center;
}
.practice-sheet {
margin: 0 auto;
max-width: 800px;
}
.letter-header {
font-size: 5rem;
margin: 30px 0;
color: #2c3e50;
${type === 'hindi' ? "font-family: 'Mangal', 'Nirmala UI', sans-serif;" : ""}
}
.instructions {
font-size: 1.5rem;
margin-bottom: 40px;
color: #7f8c8d;
}
.practice-area {
height: 600px;
border: 2px dashed #bdc3c7;
border-radius: 10px;
margin: 20px 0;
display: flex;
align-items: center;
justify-content: center;
}
.tip {
font-size: 1.2rem;
color: #7f8c8d;
margin-top: 30px;
}
@media print {
.tip {
display: none;
}
}
</style>
</head>
<body>
<div class="practice-sheet">
<h1>Handwriting Practice - ${letter}</h1>
<div class="letter-header">${letter}</div>
<div class="instructions">Trace the dashed lines to practice writing</div>
<div class="practice-area">
${svg.outerHTML.replace('180', '400').replace('180', '400')}
</div>
<div class="tip">Tip: Practice each row 5 times for best results</div>
</div>
<script>
window.onload = function() {
window.print();
};
<\/script>
</body>
</html>
`);
printWindow.document.close();
});
card.appendChild(header);
card.appendChild(practiceArea);
card.appendChild(practiceBtn);
practiceGrid.appendChild(card);
}
// Initialize with some letters
lettersInput.value = 'A,B,C,D,E';
generateBtn.click();
});
</script>
</body>
</html>Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request