এই পর্বে যা শিখবেন
- SVG ভেতরে কী — XML markup, স্থানাঙ্ক, viewBox আর preserveAspectRatio কীভাবে ঘর আর খাতা মেলায়
- ছয়টি মৌলিক আকার আর path-এর কমান্ড দিয়ে নিজের হাতে আকার আঁকা — শাপলা লোগো আর বাংলাদেশের পতাকা-রঙের ম্যাপ পিন পর্যন্ত
- fill, stroke, linecap, linejoin, dasharray দিয়ে রেখা সাজানো আর reduced motion মেনে “নিজে আঁকা হওয়া” অ্যানিমেশন
- পাতায় SVG বসানোর চার উপায়ের লাভ-ক্ষতি, sprite, currentColor আর screen reader-বান্ধব আইকন
- icon font বনাম SVG আইকন, জনপ্রিয় আইকন লাইব্রেরি, SVGO দিয়ে ছোট করা, নিরাপত্তা আর AI-এর বানানো SVG যাচাই
১ · SVG আসলে কী — আঁকার নির্দেশ, লেখা আকারে
পর্ব ০৬-এ আপনি দুই রকম ছবির কথা জেনেছেন। একটি raster ছবি — JPEG, PNG, WebP — আসলে ছোট ছোট রঙিন বিন্দুর (pixel) গ্রিড, ঠিক যেন মোজাইকের টালি। এটিকে বড় করলে টালিগুলোই বড় হয়, তাই ধার খাঁজকাটা বা ঝাপসা হয়ে যায়। অন্যটি vector ছবি — সেখানে বিন্দু জমা থাকে না, থাকে আঁকার নির্দেশ: “মাঝখানে ২০ ঘর ব্যাসার্ধের একটি লাল বৃত্ত আঁকো।” ব্রাউজার প্রতিবার পর্দার মাপ অনুযায়ী নতুন করে আঁকে, তাই মোবাইলের ছোট পর্দা থেকে ৪K মনিটর — সব জায়গায় ঝকঝকে।
একই বৃত্ত, দুই রকম জমা রাখা
8×8 pixel raster (left) vs one vector instruction (right), both shown at 120px
<circle cx="4" cy="4" r="4"> — যে মাপেই আঁকুন, গোল থাকে।SVG (Scalable Vector Graphics) হলো ওয়েবের vector ছবির ভাষা। আর এর সবচেয়ে সুন্দর দিক — এটি একটি সাধারণ লেখার ফাইল, যা XML নিয়মে লেখা। HTML-এর মতোই ট্যাগ আর attribute, শুধু ট্যাগগুলো ছবি আঁকার: <rect> (আয়তক্ষেত্র), <circle> (বৃত্ত), <path> (যেকোনো আকার)। Notepad-এ খুলে পড়া যায়, হাতে বদলানো যায়, Git-এ পরিবর্তনের হিসাব রাখা যায়। একটি আলাদা .svg ফাইল দেখতে এমন:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 60">
<rect width="100" height="60" fill="#006a4e"/>
<circle cx="45" cy="30" r="20" fill="#f42a41"/>
</svg>মাত্র চার লাইনে বাংলাদেশের পতাকা — সবুজ আয়তক্ষেত্রের ওপর লাল বৃত্ত, মাঝখান থেকে একটু বাঁয়ে। আলাদা ফাইলে xmlns="http://www.w3.org/2000/svg" অবশ্যই লাগে — এটি ব্রাউজারকে বলে “এই ট্যাগগুলো SVG-র, HTML-এর নয়।” কিন্তু HTML পাতার ভেতরে সরাসরি <svg> লিখলে (একে বলে inline SVG) HTML parser নিজেই বুঝে নেয়, তখন xmlns না দিলেও চলে।
SVG ছবি হলেও আসলে DOM. Inline SVG-র প্রতিটি বৃত্ত, প্রতিটি রেখা পাতার DOM-এ একটি element — তাই CSS দিয়ে রং বদলানো যায়, :hover দেওয়া যায়, JavaScript দিয়ে নড়ানো যায়, আর screen reader-এর জন্য নামও দেওয়া যায়। কোনো PNG ছবিতে এর কোনোটিই সম্ভব নয়।
XML-এর নিয়ম HTML-এর চেয়ে কড়া। আলাদা .svg ফাইলে একটি ট্যাগ বন্ধ করতে ভুললে ব্রাউজার পুরো ছবিই দেখাতে না-ও পারে। অভ্যাস রাখুন: প্রতিটি আকার /> দিয়ে বন্ধ, আর attribute-এর বড়-ছোট হাতের অক্ষর হুবহু (viewBox, preserveAspectRatio, pathLength).
২ · আঁকার খাতা — স্থানাঙ্ক, viewBox আর preserveAspectRatio
স্কুলের জ্যামিতি বক্সের গ্রাফ পেপারের কথা মনে করুন — (0,0) থেকে শুরু, x ডানে, y ওপরে। SVG-র খাতাও গ্রাফ পেপার, শুধু একটি পার্থক্য: (0,0) ওপরের বাঁ কোণে, আর y বাড়ে নিচের দিকে — যেভাবে আমরা খাতায় লিখি, ওপর থেকে নিচে। একে বলে SVG-র coordinate system; এর প্রতিটি ঘরকে বলে “user unit”.
এখন প্রশ্ন — খাতার এক ঘর পর্দায় কত পিক্সেল? এর উত্তর দুই জিনিস মিলিয়ে। width আর height হলো দেয়ালে ফ্রেমের মাপ — পর্দায় SVG কত জায়গা নেবে। আর viewBox হলো খাতার কোন অংশটুকু ফ্রেমে দেখানো হবে: চারটি সংখ্যা — min-x min-y width height. ব্রাউজার খাতার সেই অংশটুকু টেনে-ছোট করে ফ্রেমে বসায়। নিচে একই পতাকা-আঁকা (১০০×৬০ ঘর) নানা viewBox-এ দেখুন:
| ঘর (width×height) | |
| viewBox | |
| preserveAspectRatio | |
| ১ ঘর = |
- viewBox নেই। তখন এক ঘর = এক CSS pixel. পতাকা ১০০×৬০ pixel-এর, তাই ২৪০×১৪৪-এর ফ্রেমের ওপরের বাঁ কোণে ছোট্ট হয়ে বসে আছে। ফ্রেম বড় করলেও ছবি বড় হবে না — এজন্যই viewBox ছাড়া SVG “রেসপন্সিভ” হয় না।
viewBox="0 0 100 60". “খাতার (0,0) থেকে ১০০×৬০ ঘর দেখাও।” ফ্রেম ২৪০ চওড়া, তাই ২৪০ ÷ ১০০ = ২.৪ — এক ঘর এখন ২.৪ pixel. অনুপাত (১০০:৬০ আর ২৪০:১৪৪) হুবহু মেলে, তাই পতাকা পুরো ফ্রেম ভরে।viewBox="0 0 50 30"— zoom in. এবার খাতার মাত্র ৫০×৩০ ঘর ফ্রেমে টেনে বসানো হচ্ছে, তাই এক ঘর ৪.৮ pixel. খাতার বাকি অংশ ফ্রেমের বাইরে, দেখা যায় না। viewBox যত ছোট, ছবি তত বড় — ঠিক যেন ক্যামেরায় zoom করা।viewBox="25 0 50 30"— pan. প্রথম দুটি সংখ্যা (min-x, min-y) জানালাকে খাতার ওপর সরায়। x ২৫ থেকে শুরু, তাই বৃত্তটি এখন ফ্রেমের মাঝখানের দিকে। Google Maps-এ আঙুল দিয়ে মানচিত্র টানা আসলে এই কাজ।- অনুপাত মেলে না — ডিফল্ট
meet. ফ্রেম এবার বর্গ (১৬০×১৬০), খাতার অংশ ১০০×৬০. ব্রাউজার দুই দিকের scale হিসাব করে (১.৬ আর ২.৬৭) আর ছোটটি নেয়, যাতে পুরো ছবি দেখা যায়। বাড়তি জায়গা ওপরে-নিচে সমান ফাঁকা, কারণ ডিফল্টxMidYMid— মাঝখানে বসাও। পর্ব ৩২-এরobject-fit: contain-এর সাথে মিলিয়ে নিন। preserveAspectRatio="xMidYMid slice". এবার বড় scale (২.৬৭) নেওয়া হয়, তাই ফ্রেম পুরো ভরে যায়, আর দুই পাশের বাড়তি অংশ কেটে পড়ে —object-fit: cover-এর মতো। ব্যানারের পটভূমি-নকশায় কাজের।preserveAspectRatio="none". অনুপাতের তোয়াক্কা না করে দুই দিকে আলাদা scale — বৃত্ত চ্যাপ্টা হয়ে ডিম্বাকার। লোগোর জন্য ভয়ংকর, কিন্তু ঢেউ-আকারের section বিভাজক বা চার্টের পটভূমিতে মাঝে মাঝে ঠিক এটাই চাওয়া হয়।
preserveAspectRatio-এর মানে দুই অংশ। প্রথমটি জায়গা: xMin/xMid/xMax আর YMin/YMid/YMax জোড়া মিলিয়ে নয়টি — যেমন xMinYMin মানে ওপরের বাঁ কোণে সেঁটে দাও। দ্বিতীয়টি নীতি: meet (পুরোটা দেখাও) বা slice (ঘর ভরাও)। নিজে চালিয়ে দেখুন:
<style>
svg { border: 2px dashed #94a3b8; margin: 4px; vertical-align: top; }
</style>
<svg width="200" height="120" viewBox="0 0 100 60">
<rect width="100" height="60" fill="#006a4e"/>
<circle cx="45" cy="30" r="20" fill="#f42a41"/>
</svg>
<svg width="120" height="120" viewBox="0 0 100 60"
preserveAspectRatio="xMidYMid meet">
<rect width="100" height="60" fill="#006a4e"/>
<circle cx="45" cy="30" r="20" fill="#f42a41"/>
</svg>
<svg width="120" height="120" viewBox="0 0 100 60"
preserveAspectRatio="none">
<rect width="100" height="60" fill="#006a4e"/>
<circle cx="45" cy="30" r="20" fill="#f42a41"/>
</svg>প্রথমটিতে অনুপাত মেলে, তাই পতাকা পুরো ফ্রেম ভরা। দ্বিতীয়টি বর্গ ফ্রেমে পুরো পতাকা দেখায়, ওপরে-নিচে ফাঁকা রেখে। তৃতীয়টি টেনে লম্বা — লাল বৃত্ত এখন ডিম্বাকার। চেষ্টা করুন: দ্বিতীয়টির xMidYMid meet-কে xMidYMin meet করুন — পতাকা ফ্রেমের ওপরে সেঁটে যাবে। তারপর meet-কে slice করুন — বাঁ-ডানের অংশ কেটে যাবে, লাল বৃত্ত প্রায় মাঝখানে আসবে। প্রথমটির viewBox-কে "-20 -20 140 100" করলে খাতার বাইরের ফাঁকা অংশসহ দেখবেন — viewBox ঋণাত্মক থেকেও শুরু হতে পারে।
বাস্তবের নিয়ম: আইকন আর লোগোতে সবসময় viewBox রাখুন, আর পর্দার মাপ দিন CSS-এ (width: 1.5em বা max-width: 100%; height: auto). Inline SVG-তে width/height attribute একদম না দিলে অনেক জায়গায় সেটি পাশের সব জায়গা নিয়ে ফেলে (ডিফল্ট মাপ ৩০০×১৫০ বা পুরো চওড়া), আর CSS লোড হওয়ার আগের মুহূর্তে বিশাল আইকন দেখা যায়। তাই নিরাপদ অভ্যাস: attribute-এ ছোট একটি মাপ (যেমন width="24" height="24"), আর CSS দিয়ে আসল মাপ।
৩ · ছয়টি মৌলিক আকার — rect, circle, ellipse, line, polyline, polygon
SVG-র বেশিরভাগ ছবি এই ছয়টি আকার আর পরের অংশের <path> দিয়ে তৈরি। প্রতিটির attribute আসলে জ্যামিতির সেই চেনা মাপগুলো:
| আকার | মূল attribute | বাস্তব উদাহরণ |
|---|---|---|
<rect> আয়তক্ষেত্র | x y width height, কোণ গোল করতে rx ry | বাটন, কার্ড, পতাকার জমিন |
<circle> বৃত্ত | কেন্দ্র cx cy, ব্যাসার্ধ r | নোটিফিকেশন বিন্দু, পতাকার সূর্য |
<ellipse> উপবৃত্ত | cx cy, দুই ব্যাসার্ধ rx ry | ছায়া, ডিম, চোখ |
<line> রেখা | দুই প্রান্ত x1 y1 x2 y2 | বিভাজক, চার্টের অক্ষ |
<polyline> ভাঙা রেখা | points="x,y x,y …" — খোলা থাকে | শেয়ারবাজারের লাইন চার্ট |
<polygon> বহুভুজ | points — শেষ বিন্দু নিজে থেকে প্রথমটির সাথে জোড়া | তারা, ত্রিভুজ, তীরের মাথা |
<svg width="340" height="210" viewBox="0 0 340 210" style="background:#f8fafc">
<rect x="10" y="10" width="90" height="60" rx="10" fill="#0ea5e9"/>
<circle cx="170" cy="40" r="30" fill="#f42a41"/>
<ellipse cx="275" cy="40" rx="50" ry="25" fill="#f59e0b"/>
<line x1="10" y1="110" x2="100" y2="160" stroke="#334155" stroke-width="4"/>
<polyline points="130,160 160,105 190,145 220,100"
fill="none" stroke="#16a34a" stroke-width="4"/>
<polygon points="275,100 320,160 230,160" fill="#8b5cf6"/>
<text x="10" y="195" font-size="13" fill="#334155">
rect · circle · ellipse · line · polyline · polygon
</text>
</svg>ওপরের সারিতে গোল-কোণা নীল আয়তক্ষেত্র, লাল বৃত্ত আর কমলা উপবৃত্ত; নিচের সারিতে ধূসর তেরছা রেখা, সবুজ আঁকাবাঁকা চার্ট-রেখা আর বেগুনি ত্রিভুজ। SVG-র ভেতরের লেখা (<text>) আসল লেখা — select করা যায়, screen reader পড়তে পারে। চেষ্টা করুন: <polyline-কে <polygon করুন (ট্যাগটি /> দিয়ে নিজেই বন্ধ, তাই শুধু নামটি বদলালেই হবে) — রেখাটি নিজে থেকে বন্ধ হয়ে যাবে। তারপর fill="none" মুছে দিন — ভেতরটা কালো হয়ে যাবে, কারণ SVG-তে fill-এর ডিফল্ট কালো।
একটি জিনিস খেয়াল করুন: SVG-র আকারগুলো HTML-এর box-এর মতো একে অপরকে ঠেলে সরায় না। সব আকার নিজের স্থানাঙ্কে বসে, আর পরে লেখা আকার আগেরটির ওপরে আঁকা হয় — যেমন কাগজের ওপর কাগজ রাখা। SVG-তে z-index কাজ করে না; সামনে আনতে হলে কোডে পরে লিখতে হয়। এজন্যই পতাকায় আগে সবুজ rect, তারপর লাল circle.
৪ · path — এক element-এ যেকোনো আকার
ছয়টি আকার দিয়ে সব কিছু আঁকা যায় না — শাপলার পাপড়ি, হৃদয়, ম্যাপ পিন, বা কোনো ব্র্যান্ডের লোগো। এজন্য আছে <path>. ধারণাটি খুব সরল: আপনি একটি কলমকে ধাপে ধাপে নির্দেশ দিচ্ছেন — “এখানে কলম রাখো, ওখানে রেখা টানো, এভাবে বাঁকাও, শেষে বন্ধ করো।” নির্দেশগুলো লেখা হয় d attribute-এ, এক অক্ষরের কমান্ড আর তার পরে সংখ্যা দিয়ে।
| কমান্ড | মানে | উদাহরণ |
|---|---|---|
M x y | Move — কলম তুলে নতুন জায়গায় রাখো, দাগ পড়ে না | M 20 60 |
L x y | Line — এখান থেকে ওই বিন্দু পর্যন্ত সোজা রেখা | L 50 25 |
H x / V y | শুধু আড়াআড়ি / শুধু খাড়া রেখা | H 20, V 95 |
Q cx cy x y | এক control point-এর বাঁক | Q 50 64 58 78 |
C c1x c1y c2x c2y x y | দুই control point-এর বাঁক — সবচেয়ে নমনীয় | C 30 95 70 115 95 105 |
A rx ry ঘূর্ণন বড়-চাপ দিক x y | Arc — উপবৃত্তের একটি অংশ | A 8 8 0 0 1 94 18 |
Z | যেখান থেকে শুরু, সেখানে ফিরে আকার বন্ধ করো | Z |
বড় হাতের অক্ষর (L) মানে খাতার আসল স্থানাঙ্ক (absolute); ছোট হাতের (l) মানে “এখন কলম যেখানে, সেখান থেকে এত দূরে” (relative). আইকন-টুলগুলো প্রায়ই ছোট হাতের কমান্ড লেখে, কারণ সংখ্যাগুলো ছোট হয়, ফাইলও ছোট হয়। এবার একটি গ্রামের ঘর, পাশে ধানক্ষেতের আল আর আকাশে সূর্য — ধাপে ধাপে আঁকি:
1M 20 602L 50 253L 80 604V 955H 206Z7M 42 95 V 78 Q 50 64 58 78 V 958M 5 105 C 30 95, 70 115, 95 1059M 78 18 A 8 8 0 0 1 94 1810 A 8 8 0 0 1 78 18 Z
| কলম কোথায় | |
| দাগ পড়ল? |
M 20 60— কলম রাখা। M (Move) কোনো দাগ ফেলে না, শুধু কলমকে (২০, ৬০) বিন্দুতে বসায় — নীল বিন্দুটি দেখুন। প্রতিটি path শুরু হয় M দিয়ে। হালকা ছায়ায় পুরো ছবিটি আগাম দেখা যাচ্ছে, যাতে বোঝেন কোথায় যাচ্ছি।L 50 25— চালের বাঁ দিক। L (Line) বর্তমান জায়গা থেকে (৫০, ২৫) পর্যন্ত সোজা রেখা টানে। y কমেছে (৬০ → ২৫), তাই রেখা ওপরে উঠেছে — মনে রাখুন, SVG-তে y নিচের দিকে বাড়ে।L 80 60— চালের ডান দিক। আবার সোজা রেখা, এবার নিচে নেমে (৮০, ৬০)। দুই রেখা মিলে ঘরের দোচালা তৈরি হলো।V 95— ডানের দেয়াল। V (Vertical) শুধু y নেয়, x আগেরটাই থাকে। খাড়া রেখার জন্যL 80 95লেখার চেয়ে ছোট — বড় আইকনে এমন সাশ্রয় ফাইলকে বেশ ছোট করে।H 20— মেঝে। H (Horizontal) শুধু x নেয়। কলম ডান থেকে বাঁয়ে (২০, ৯৫)-এ এলো।Z— আকার বন্ধ। Z কলমকে শুরুর বিন্দু (২০, ৬০)-এ ফিরিয়ে আনে আর আকারটিকে “বন্ধ” ঘোষণা করে — তাই এখন ভেতরটা হলুদ fill দিয়ে ভরানো যায়। শেষ বিন্দু হাতে L দিয়ে জুড়লে দেখতে প্রায় এক, কিন্তু কোণের জোড়া (linejoin) ঠিকমতো হয় না — Z-ই সঠিক।- দরজা — নতুন M আর
Qবাঁক। এক path-এ একাধিক M মানে একাধিক টুকরো (subpath). দরজার বাঁ পাশ খাড়া উঠে, তারপরQ 50 64 58 78: (৫০, ৬৪) হলো control point — বাঁকটিকে চুম্বকের মতো ওপরে টানে, কিন্তু বাঁক নিজে সেখানে পৌঁছায় না। ফল: খিলান-আকারের দরজা। - ধানক্ষেতের আল —
Cবাঁক। C-তে দুটি control point: প্রথমটি (৩০, ৯৫) শুরুর দিকটা ওপরে টানে, দ্বিতীয়টি (৭০, ১১৫) শেষের দিকটা নিচে। ফলে S-আকারের ঢেউ। ডিজাইন টুলে যে “হ্যান্ডেল” টেনে বাঁক বানান, সেগুলোই এই control point — এরা Bézier curve-এর অংশ। - সূর্য —
Aদিয়ে বৃত্তচাপ।A 8 8 0 0 1 94 18: ব্যাসার্ধ ৮ আর ৮, ঘূর্ণন ০, “বড় চাপ নয়” (০), “ঘড়ির কাঁটার দিকে” (১), গন্তব্য (৯৪, ১৮)। এতে ওপরের অর্ধবৃত্ত হলো; দ্বিতীয় A ফিরে আসে নিচ দিয়ে। একটি A দিয়ে পুরো বৃত্ত হয় না, কারণ শুরু আর শেষ এক বিন্দু হলে ব্রাউজার কিছুই আঁকে না — তাই দুই টুকরো। পুরো বৃত্তের জন্য অবশ্য<circle>-ই সহজ।
এবার নিজে একটি path সম্পাদনা করুন। বাংলাদেশের পতাকার রঙে একটি ম্যাপ পিন — যেকোনো “আমাদের দোকান কোথায়” পাতার চেনা আইকন। দুটি C বাঁক আর একটি A চাপ দিয়ে পুরো ফোঁটা-আকার:
<svg width="150" height="180" viewBox="0 0 100 120"
role="img" aria-label="ম্যাপ পিন">
<path d="M 50 110
C 35 90, 15 70, 15 45
A 35 35 0 0 1 85 45
C 85 70, 65 90, 50 110 Z"
fill="#006a4e"/>
<circle cx="50" cy="45" r="15" fill="#f42a41"/>
</svg>
<p>মিরপুর ১০, ঢাকা</p>সবুজ ফোঁটা-আকারের পিন, ভেতরে লাল বৃত্ত। path শুরু হয় নিচের সূক্ষ্ম মাথা (৫০, ১১০) থেকে, বাঁ দিকে C বাঁকে ওঠে, A দিয়ে মাথার ওপর অর্ধবৃত্ত ঘুরে ডানে নামে, আবার C দিয়ে মাথায় ফেরে। লাইন ভেঙে লেখা যায় — কমান্ডের মাঝের ফাঁকা জায়গা আর কমা ব্রাউজারের কাছে সমান। চেষ্টা করুন: প্রথম C-এর 35 90-কে 15 100 করুন — বাঁ দিক ফুলে উঠবে। তারপর A-এর 0 1-কে 0 0 করুন — চাপ উল্টো দিক দিয়ে (নিচ দিয়ে) ঘুরবে, পিনের মাথা ভেতরে ঢুকে যাবে।
বড় লোগোর path কেউ হাতে লেখেন না — Figma, Inkscape বা Illustrator থেকে export করেন। তবু কমান্ড চেনা দরকার: ছোট আইকন ঠিক করতে আর AI বা টুলের দেওয়া path পড়ে বুঝতে। মাঝে মাঝে S আর T-ও দেখবেন — আগের বাঁকের control point-কে আয়নার মতো উল্টে নিয়ে “মসৃণভাবে চালিয়ে যাও” (smooth) বোঝায়।
৫ · রং আর রেখা — fill, stroke আর নিজে আঁকা হওয়া রেখা
প্রতিটি SVG আকারের দুটি অংশে রং পড়ে: ভেতরটা (fill) আর কিনারা (stroke). আলপনা আঁকার কথা ভাবুন — আগে চালের গুঁড়ি দিয়ে রেখা টানা (stroke), তারপর ভেতরে রং ভরানো (fill). রেখার আরও কয়েকটি নিয়ন্ত্রণ আছে:
stroke-width— রেখা কত মোটা। রেখা আকারের কিনারার মাঝ বরাবর আঁকা হয় — অর্ধেক ভেতরে, অর্ধেক বাইরে।stroke-linecap— খোলা রেখার মাথা:butt(ডিফল্ট, সমান কাটা),round(গোল),square(চারকোনা, রেখার চেয়ে একটু বাড়তি)।stroke-linejoin— দুই রেখার কোণ:miter(ডিফল্ট, ধারালো),round(গোল),bevel(কোণ ছাঁটা)।stroke-dasharray— রেখাকে দাগ-ফাঁকে ভাঙা;"12 6"মানে ১২ ঘর দাগ, ৬ ঘর ফাঁক।
এই সবকটি CSS property-ও। নিচের এডিটরে HTML নির্দিষ্ট — শুধু CSS বদলান:
svg { background: #f8fafc; font: 13px sans-serif; }
polyline { fill: none; stroke: #0f766e; stroke-width: 14; }
.a { stroke-linecap: butt; stroke-linejoin: miter; }
.b { stroke-linecap: round; stroke-linejoin: round; }
.c { stroke-linecap: square; stroke-linejoin: bevel; }
/* পাতলা সাদা রেখা = path-এর আসল পথ */
.guide { stroke: #fff; stroke-width: 1.5; }
.d { stroke: #f42a41; stroke-width: 6; stroke-dasharray: 20 10; }
.e { fill: #fde68a; stroke: #b45309; stroke-width: 4; }তিনটি মোটা সবুজ “^” চিহ্ন: প্রথমটির মাথা সমান কাটা আর চূড়া ধারালো, দ্বিতীয়টির মাথা ও চূড়া গোল, তৃতীয়টির মাথা চারকোনা আর চূড়া ছাঁটা। পাতলা সাদা রেখা দেখাচ্ছে আসল পথ — খেয়াল করুন, round আর square মাথা পথের শেষ বিন্দু ছাড়িয়ে বাইরে যায়। নিচে লাল দাগ-ফাঁকের রেখা আর হলুদ-কমলা বৃত্ত। চেষ্টা করুন: .d-তে stroke-dasharray-কে 2 10 করুন আর stroke-linecap: round; যোগ করুন — দাগগুলো গোল বিন্দু হয়ে যাবে (ডট-লাইন)। তারপর .e-তে paint-order: stroke; যোগ করুন — stroke এবার fill-এর নিচে আঁকা হবে, তাই বৃত্তের রেখা অর্ধেক পাতলা দেখাবে।
রেখা নিজে আঁকা হওয়ার কৌশল — dasharray আর dashoffset
অনেক ওয়েবসাইটে দেখেছেন, লোগো বা স্বাক্ষর যেন অদৃশ্য কলমে চোখের সামনে আঁকা হচ্ছে। এর পেছনে কোনো জটিল JavaScript নেই — আছে stroke-dasharray আর stroke-dashoffset-এর একটি চালাক কৌশল। মূল ভাবনা: যদি একটি দাগ পুরো রেখার সমান লম্বা হয়, আর তার পরের ফাঁকও সমান লম্বা, তাহলে দাগ-ফাঁকের নকশাকে একটু একটু সরালে মনে হবে রেখাটি আঁকা হচ্ছে। ধাপে ধাপে দেখুন:
1<path pathLength="100" d="M 10 50 C …"/>23.river {4 stroke-dasharray: ;5 stroke-dashoffset: ;6}
- সাধারণ রেখা। একটি ঢেউ-খেলানো নদী-রেখা (C আর S বাঁক)। পেছনের হালকা ধূসর রেখাটি শুধু পথ দেখানোর জন্য, সব ধাপে থাকবে।
pathLength="100"ব্রাউজারকে বলে, “এই রেখার আসল দৈর্ঘ্য যা-ই হোক, হিসাবে ১০০ ধরো।” তাহলে দাগের মাপ শতাংশের মতো লেখা যায়। stroke-dasharray: 12 6. রেখা এখন ১২ ঘর দাগ, ৬ ঘর ফাঁক, আবার ১২ দাগ… এভাবে পুনরাবৃত্তি। রাস্তার মাঝখানের সাদা দাগের মতো।stroke-dashoffset: 6. offset পুরো নকশাটিকে রেখা বরাবর পেছনের দিকে ৬ ঘর সরায় — দাগগুলোর জায়গা বদলেছে, রেখা নয়। এই offset ধীরে ধীরে বদলালে দাগগুলো “চলতে” থাকে — মিছিলের মতো।- চালাকি: দাগ = পুরো দৈর্ঘ্য, offset = পুরো দৈর্ঘ্য।
dasharray: 100মানে ১০০ ঘর দাগ, ১০০ ঘর ফাঁক — পুরো রেখাই একটি দাগ। কিন্তুoffset: 100সেই দাগকে পুরোটা সরিয়ে দিয়েছে, এখন রেখার জায়গায় শুধু ফাঁক। কিছুই দেখা যায় না। offset: 50. দাগটি অর্ধেক ফিরে এসেছে — রেখার শুরু থেকে অর্ধেক আঁকা। offset ১০০ থেকে ০-এর দিকে যত কমে, তত বেশি রেখা দেখা যায়।offset: 0— শেষ। দাগ পুরো রেখা ঢেকে দিয়েছে। এখন CSS animation দিয়ে offset ১০০ থেকে ০-তে নিয়ে গেলেই নিজে আঁকা হওয়ার অ্যানিমেশন।pathLengthনা দিলে JavaScript-এরpath.getTotalLength()দিয়ে আসল দৈর্ঘ্য মেপে সেই সংখ্যা বসাতে হতো।
এবার আসল অ্যানিমেশন — আর সাথে সেই নিয়ম, যা পর্ব ৩৮ থেকে বারবার আসছে: যাঁরা অপারেটিং সিস্টেমে “অ্যানিমেশন কমান” চালু রেখেছেন (চলমান জিনিসে যাঁদের মাথা ঘোরে বা মনোযোগ হারায়), তাঁদের জন্য prefers-reduced-motion-এ অ্যানিমেশন বন্ধ করে সরাসরি শেষ অবস্থা দেখান।
<style>
.river {
fill: none; stroke: #0369a1; stroke-width: 6; stroke-linecap: round;
stroke-dasharray: 100;
stroke-dashoffset: 100;
animation: draw 3s ease-in-out infinite alternate;
}
@keyframes draw { to { stroke-dashoffset: 0; } }
@media (prefers-reduced-motion: reduce) {
.river { animation: none; stroke-dashoffset: 0; }
}
</style>
<svg width="300" height="100" viewBox="0 0 300 100" aria-hidden="true">
<path class="river" pathLength="100"
d="M 10 50 C 60 0, 110 100, 160 50 S 260 0, 290 50"/>
</svg>
<p>পদ্মার ঢেউ — রেখাটি নিজে নিজে আঁকা হচ্ছে।</p>নীল নদী-রেখাটি বাঁ থেকে ডানে ধীরে আঁকা হয়, তারপর উল্টো দিকে মুছে যায় (alternate), আবার আঁকা হয়। আপনার অপারেটিং সিস্টেমে অ্যানিমেশন কমানোর সেটিং চালু থাকলে রেখাটি স্থির, পুরোটা আঁকা অবস্থায় দেখাবে — এটি ইচ্ছাকৃত। ছবিটি শুধু সাজ, তাই aria-hidden="true". চেষ্টা করুন: stroke-dasharray: 100-কে stroke-dasharray: 20 80 করুন — এবার একটি ছোট টুকরো রেখা বরাবর ছুটবে, যেন নদীতে নৌকা। তারপর 3s-কে 1s করুন।
৬ · গুছিয়ে রাখা আর বারবার ব্যবহার — g, defs, use আর symbol
বড় ছবিতে শত শত আকার থাকে। সেগুলো গুছিয়ে রাখার তিনটি হাতিয়ার:
<g> — দল
<g> কয়েকটি আকারকে এক দলে রাখে। দলে fill, stroke বা transform দিলে ভেতরের সবার ওপর খাটে — HTML-এর <div>-এর মতো, তবে নিজের কোনো box নেই।
<defs> + <use>
<defs>-এ রাখা আকার নিজে আঁকা হয় না — শুধু জমা থাকে। <use href="#id"> সেটিকে ডেকে এনে যেখানে খুশি, যতবার খুশি দেখায়।
<symbol>
<symbol> হলো নিজের viewBox-সহ একটি টেমপ্লেট। <use> দিয়ে ডাকার সময় যে মাপই দিন, সেটি নিজের viewBox মেনে ঠিকঠাক ছোট-বড় হয় — আইকনের জন্য আদর্শ।
একটি উদাহরণে তিনটিই দেখি — বাংলাদেশের জাতীয় ফুল শাপলার একটি সরল লোগো। পাপড়ি মাত্র একবার আঁকা, তারপর <use> দিয়ে পাঁচবার, প্রতিবার rotate() দিয়ে একটু ঘুরিয়ে:
<svg width="240" height="220" viewBox="0 0 120 110"
role="img" aria-labelledby="logo-title">
<title id="logo-title">শাপলা ফুলের লোগো</title>
<defs>
<path id="petal" d="M 60 70 Q 46 44 60 16 Q 74 44 60 70 Z"/>
</defs>
<g fill="#f9a8d4" stroke="#be185d" stroke-width="1">
<use href="#petal" transform="rotate(-64 60 70)"/>
<use href="#petal" transform="rotate(64 60 70)"/>
<use href="#petal" transform="rotate(-32 60 70)"/>
<use href="#petal" transform="rotate(32 60 70)"/>
<use href="#petal"/>
</g>
<circle cx="60" cy="68" r="7" fill="#facc15"/>
<g fill="none" stroke="#0284c7" stroke-width="3" stroke-linecap="round">
<path d="M 8 86 q 13 -8 26 0 t 26 0 t 26 0 t 26 0"/>
<path d="M 21 98 q 13 -8 26 0 t 26 0 t 26 0"/>
</g>
</svg>পাঁচটি গোলাপি পাপড়ি পাখার মতো ছড়ানো, মাঝে হলুদ কেন্দ্র, নিচে দুই সারি নীল ঢেউ। পাপড়ির আকার <defs>-এ একবারই লেখা; rotate(-64 60 70) মানে “(৬০, ৭০) বিন্দুকে কেন্দ্র করে ৬৪ ডিগ্রি বাঁয়ে ঘোরাও” — পাপড়ির গোড়া ওই বিন্দুতে, তাই সব পাপড়ি এক জায়গা থেকে ছড়ায়। রং দেওয়া হয়েছে <g>-এ, পাঁচটি পাপড়ি সেটি উত্তরাধিকারে পায়। ঢেউয়ে ছোট হাতের q আর t — relative কমান্ড, তাই একই “২৬ ঘর এগিয়ে ঢেউ” বারবার লেখা গেছে। চেষ্টা করুন: <g>-এর fill-কে #ffffff করুন — আসল শাপলার মতো সাদা হবে। তারপর rotate(-90 60 70) আর rotate(90 60 70) দিয়ে আরও দুটি <use> যোগ করুন।
এখানে href লেখা হয়েছে, xlink:href নয়। পুরোনো SVG 1.1-এ xlink:href লাগত; SVG 2-তে সাধারণ href, আর সব আধুনিক ব্রাউজার এটি চেনে। পুরোনো টিউটোরিয়াল আর AI-এর কোডে এখনো xlink:href দেখবেন — কাজ করে, কিন্তু নতুন কোডে দরকার নেই।
<use> আসলে আকারটি কপি করে না, ব্রাউজার ভেতরে একটি লুকানো কপি-গাছ তৈরি করে — shadow tree. এর একটি বাস্তব ফল আছে: পাতার CSS selector (যেমন #petal path) সেই কপির ভেতরে পৌঁছায় না। ভেতরে যায় শুধু উত্তরাধিকারে পাওয়া property — fill, stroke, color — আর CSS variable. তাই একই আইকনের দুই জায়গায় দুই রং চাইলে symbol-এর ভেতরে রং “হার্ডকোড” না করে fill="currentColor" বা fill="var(--accent)" লিখুন, আর <use>-এ বা তার বাবা-মায়ে রং দিন।
৭ · পাতায় SVG বসানোর চার উপায় — কোনটির কী লাভ-ক্ষতি
একই SVG ছবি পাতায় চারভাবে আনা যায়, আর প্রতিটির আচরণ আলাদা। দোকানের সাইনবোর্ডের উদাহরণ নিন: (১) দেয়ালে নিজে রং-তুলি দিয়ে আঁকা — যখন খুশি রং বদলানো যায় (inline); (২) ছাপা ব্যানার টাঙানো — বদলানো যায় না, কিন্তু একই ব্যানার অনেক শাখায় লাগানো যায় (img); (৩) দেয়ালের ওয়ালপেপার — শুধু সাজ (CSS background); (৪) দেয়ালে একটি টিভি বসানো — ভেতরে আলাদা জগৎ চলে (object).
| উপায় | পাতার CSS দিয়ে ভেতরে রং বদল | আলাদা cache | ভেতরের script | অ্যাক্সেসিবিলিটি | কখন |
|---|---|---|---|---|---|
Inline <svg>…</svg> | হ্যাঁ — পুরোটাই DOM | না, HTML-এর অংশ | চলে (পাতার অংশ হিসেবে) | <title>, role, aria-* | আইকন, রং-বদলানো বা অ্যানিমেটেড ছবি |
<img src="logo.svg"> | না | হ্যাঁ | চলে না | alt | লোগো, ইলাস্ট্রেশন, ব্যবহারকারীর ছবি |
CSS background-image: url(…) | না | হ্যাঁ | চলে না | নেই — screen reader জানে না | শুধু সাজসজ্জার নকশা |
<object data="map.svg"> | না (নিজের আলাদা ডকুমেন্ট) | হ্যাঁ | চলে (নিজের ডকুমেন্টে) | ভেতরের fallback লেখা | কদাচিৎ — ইন্টারঅ্যাকটিভ আলাদা SVG |
সবচেয়ে বড় পার্থক্যটি নিজে চোখে দেখুন — একই ত্রিভুজ, একবার inline, একবার <img>-এ (এখানে ফাইলের বদলে data: URL ব্যবহার করা হয়েছে, যাতে আলাদা ফাইল না লাগে):
<style>
.tri { width: 64px; height: 64px; }
svg.tri { fill: #16a34a; }
.tri:hover { fill: #dc2626; }
</style>
<p>inline SVG (মাউস রাখুন):
<svg class="tri" viewBox="0 0 24 24" aria-hidden="true">
<path d="M12 2 L22 22 H2 Z"/>
</svg>
</p>
<p>একই আকার <img> দিয়ে:
<img class="tri" alt="সবুজ ত্রিভুজ" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2 L22 22 H2 Z' fill='%2316a34a'/%3E%3C/svg%3E">
</p>
<script>
console.log('পাতার DOM-এ path পাওয়া গেল:', document.querySelectorAll('path').length, 'টি');
</script>দুটি সবুজ ত্রিভুজ দেখতে হুবহু এক। কিন্তু মাউস রাখলে শুধু প্রথমটি লাল হয় — <img>-এর ভেতরে পাতার CSS পৌঁছায় না। নিচের লগ বলবে DOM-এ মাত্র ১টি path — img-এর ভেতরেরটি পাতার DOM-এ নেই, সেটি ব্রাউজারের কাছে শুধুই একটি ছবি। চেষ্টা করুন: data URL-এর ভেতরে %2316a34a-কে %232563eb করুন — দ্বিতীয়টি নীল হবে (%23 মানে #; URL-এর ভেতরে #-কে এভাবে লিখতে হয়)। তারপর svg.tri-কে শুধু .tri করে দেখুন — img-এ fill কোনো কাজই করে না, কারণ fill শুধু SVG-র আকারের property.
কোনটি কখন — বাস্তব সিদ্ধান্ত
- Inline: সবচেয়ে বেশি নিয়ন্ত্রণ, কোনো বাড়তি HTTP request নেই। কিন্তু ব্রাউজার আলাদা করে cache করতে পারে না — প্রতিটি পাতায় একই লোগো inline থাকলে প্রতিবার আবার নামে, আর বড় ছবি HTML-কে ভারী করে। ছোট আইকনের জন্য সেরা।
<img>: একবার নামলে cache থেকে আসে, script চলে না বলে সবচেয়ে নিরাপদ,loading="lazy"-ও চলে। লোগো আর বড় ইলাস্ট্রেশনের জন্য প্রথম পছন্দ। পর্ব ০৬-এর নিয়ম মেনেwidth/heightদিন।- CSS background আর
<object>: প্রথমটি শুধু নকশার জন্য (screen reader এটি জানতেই পারে না); দ্বিতীয়টি SVG-কে iframe-এর মতো আলাদা ডকুমেন্ট হিসেবে চালায় — আজকাল কদাচিৎ দরকার হয়।
একটি আধুনিক মাঝামাঝি পথ: ফাইলটি cache-ও হবে, আবার লেখার রঙেও রাঙাবে — এমন চাইলে CSS mask ব্যবহার করা যায়: .icon { background-color: currentColor; mask: url(cart.svg) center / contain no-repeat; }. SVG-র আকারটি এখানে “ছাঁচ” হিসেবে কাজ করে, আর রং আসে background-color থেকে। prefix ছাড়া mask এখন সব প্রধান ব্রাউজারে চলে (Baseline); বেশ পুরোনো ব্রাউজারে -webkit-mask লাগত। mask-এর পুরো গল্প পর্ব ৪১-এ। আর cPanel-এর হোস্টিংয়ে <img src="logo.svg"> না দেখালে DevTools-এর Network প্যানেলে দেখুন server Content-Type: image/svg+xml পাঠাচ্ছে কি না — ভুল MIME type পেলে ব্রাউজার ছবিটি দেখায় না।
৮ · CSS দিয়ে SVG সাজানো, currentColor আর অ্যাক্সেসিবল আইকন
Inline SVG-র attribute আর CSS-এর সম্পর্কটি একটু বিশেষ। fill="red"-এর মতো attribute-কে বলে presentation attribute — দেখতে attribute, কাজে CSS property. এদের specificity শূন্য, ক্যাসকেডে সবার আগে বসে। তাই path { fill: blue; }-এর মতো সবচেয়ে দুর্বল CSS নিয়মও fill="red"-কে হারিয়ে দেয়; শুধু style="fill: red" (inline style) CSS-এর চেয়ে শক্তিশালী। ডিজাইন টুল থেকে আসা SVG-তে রং প্রায়ই style="…"-এ থাকে — তখন আপনার CSS কাজ না করলে কারণ এটাই।
currentColor — লেখার রঙে আইকন
পর্ব ২০-এ currentColor দেখেছেন — “এই element-এর color যা, সেটাই।” আইকনে এর জাদু হলো: fill="currentColor" বা stroke="currentColor" দিলে আইকন তার চারপাশের লেখার রং নিয়ে নেয়। বাটনের লেখা hover-এ সাদা হলে আইকনও সাদা, লিংকের লেখা নীল হলে আইকনও নীল, ডার্ক মোডে লেখা হালকা হলে আইকনও — একটি লাইন CSS-ও লিখতে হয় না। আরও বড় সুবিধা: Windows-এর high contrast মোডে (forced colors) ব্রাউজার লেখার রং বদলে দেয়; currentColor আইকন সেই রং মেনে চলে, কিন্তু হার্ডকোড করা fill="#333" আইকন কালো পটভূমিতে হারিয়ে যেতে পারে।
আইকন কখন “ছবি”, কখন “সাজ”
Screen reader-এর কাছে একটি আইকনের তিন রকম ভূমিকা হতে পারে, আর প্রতিটির নিয়ম আলাদা:
| পরিস্থিতি | সঠিক markup | screen reader যা বলে |
|---|---|---|
| আইকনের পাশে লেখা আছে (🛒 কার্টে যোগ করুন) | <svg aria-hidden="true"> | “কার্টে যোগ করুন, বাটন” — আইকন চুপ |
| শুধু আইকন, লেখা নেই (🔍 বাটন) | <button aria-label="খুঁজুন"> + ভেতরের svg-তে aria-hidden="true" | “খুঁজুন, বাটন” |
| অর্থবহ ছবি — লোগো, চার্ট, মানচিত্র | <svg role="img" aria-labelledby="t"><title id="t">… বা role="img" aria-label="…" | “শাপলা ফুলের লোগো, ছবি” |
aria-hidden="true" আইকনটিকে accessibility tree থেকে সরিয়ে দেয় — পাশে লেখা থাকলে আইকনের নাম শোনানো মানে একই কথা দুবার বলা (“কার্ট কার্টে যোগ করুন”)। আর অর্থবহ SVG-তে role="img" বলে দেয় “পুরোটা একটি ছবি, ভেতরের শত শত path আলাদা করে ঘোষণা কোরো না।” <title> হলো SVG-র নিজস্ব নাম-ট্যাগ; অনেক ব্রাউজার মাউস রাখলে tooltip হিসেবেও দেখায়। কিছু screen reader-ব্রাউজার জোড়ায় শুধু <title> নির্ভরযোগ্যভাবে পড়া হয়নি বলে aria-labelledby দিয়ে জুড়ে দেওয়া, বা সরাসরি aria-label দেওয়া নিরাপদ অভ্যাস।
এবার সব একসাথে: দুটি আইকনের sprite, currentColor, আর দুই রকম বাটন — একটির পাশে লেখা, একটি শুধু আইকন:
<style>
body { font-family: sans-serif; }
button { display: inline-flex; align-items: center; gap: 6px; font-size: 16px;
padding: 8px 14px; color: #1d4ed8; background: #fff;
border: 2px solid currentColor; border-radius: 8px; }
button:hover { color: #fff; background: #1d4ed8; }
.icon { width: 1.25em; height: 1.25em; fill: none; stroke: currentColor;
stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
</style>
<svg style="display: none">
<symbol id="i-cart" viewBox="0 0 24 24"><path d="M3 4h2l2 11h11l2-8H6"/>
<circle cx="9" cy="20" r="1.5"/><circle cx="17" cy="20" r="1.5"/></symbol>
<symbol id="i-search" viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/>
<path d="M20 20l-4-4"/></symbol>
</svg>
<button><svg class="icon" aria-hidden="true"><use href="#i-cart"/></svg> কার্টে যোগ করুন</button>
<button aria-label="খুঁজুন"><svg class="icon" aria-hidden="true"><use href="#i-search"/></svg></button>
<p style="color: #b91c1c">লাল লেখার পাশে একই আইকন:
<svg class="icon" aria-hidden="true"><use href="#i-search"/></svg></p>
<script>
document.querySelectorAll('button').forEach(b =>
console.log('বাটনের নাম:', b.getAttribute('aria-label') || b.textContent.trim()));
</script>নীল বর্ডারের দুটি বাটন — একটিতে কার্ট-আইকন আর লেখা, অন্যটিতে শুধু খোঁজার আতশ কাচ; নিচে লাল লেখার পাশে একই আতশ কাচ, এবার লাল। মাউস রাখলে বাটন নীল হয় আর আইকন লেখার সাথে সাদা — আইকনের CSS-এ কোনো রং লেখাই নেই, সব আসছে currentColor থেকে। লগে দুই বাটনের নাম: “কার্টে যোগ করুন” আর “খুঁজুন” — screen reader ঠিক এটাই শোনাবে। Sprite-টি display: none, কারণ <symbol> শুধু ডাকলে দেখা দেয়। চেষ্টা করুন: দ্বিতীয় বাটন থেকে aria-label="খুঁজুন" মুছুন — লগে নাম খালি আসবে; এটাই আইকন-বাটনের সবচেয়ে সাধারণ অ্যাক্সেসিবিলিটি ভুল। তারপর .icon-এ stroke-width: 2-কে 1.25 করুন — আইকন হালকা, অভিজাত দেখাবে।
এই কৌশলটিকে বলে SVG sprite: সব আইকন একটি SVG-তে <symbol> হিসেবে, পাতায় শুধু <use href="#i-cart">. বড় সাইটে sprite-টি আলাদা ফাইলেও রাখা যায় — <use href="/icons.svg#i-cart"> — তখন ফাইলটি cache হয়। শর্ত: ফাইলটি একই origin-এর হতে হবে; অন্য ডোমেইন বা CDN থেকে <use> দিয়ে আনা ব্রাউজার আটকে দেয়।
৯ · icon font বনাম SVG, আইকন লাইব্রেরি, SVGO আর নিরাপত্তা
Icon font — একসময়ের রাজা
২০১০-এর দশকের শুরুতে আইকন দেখানোর জনপ্রিয় উপায় ছিল icon font: একটি web font, যার অক্ষর-ঘরে অক্ষরের বদলে ছোট ছবি। <i class="fa fa-home"></i> লিখলে CSS একটি বিশেষ অক্ষর বসিয়ে দেয়, আর font সেই অক্ষরকে বাড়ির ছবি হিসেবে আঁকে। সুবিধা ছিল বাস্তব: এক ফাইলে শত আইকন, লেখার মতোই color আর font-size দিয়ে রং-মাপ বদল, আর Internet Explorer-এর পুরোনো সংস্করণেও চলত, যেখানে SVG চলত না।
কিন্তু সময়ের সাথে সমস্যাগুলো স্পষ্ট হলো:
- অ্যাক্সেসিবিলিটি: আইকনগুলো থাকে Unicode-এর Private Use Area-তে — এমন অক্ষর, যার কোনো সার্বজনীন অর্থ নেই। screen reader কখনো অর্থহীন কিছু পড়ে, কখনো কিছুই না। যেসব font ligature কৌশলে “home” শব্দকে বাড়ি বানায়, সেখানে screen reader “home” শব্দটিই পড়ে ফেলতে পারে।
- font না এলে: ধীর নেটওয়ার্কে font নামার আগে আইকনের জায়গা ফাঁকা থাকে (FOIT), নামতে ব্যর্থ হলে চারকোনা বাক্স (tofu) বা “home” লেখা দেখা যায়। আবার যে পাঠক নিজের পড়ার সুবিধায় ব্রাউজারে সব font বদলে দেন (যেমন ডিসলেক্সিয়া-বান্ধব font), তাঁর পর্দায় আইকন ভেঙে যায়।
- আঁকার মান: ব্রাউজার আইকনকে লেখা হিসেবে আঁকে — লেখার মতো anti-aliasing আর line-height-এর হিসাব, তাই কখনো ঝাপসা বা আধা pixel সরে থাকা আইকন।
- এক রং, এক ফাইল: সাধারণত এক রঙের বেশি নয়, আর দশটি আইকন দরকার হলেও প্রায়ই পুরো font নামাতে হয়।
এজন্য ২০১০-এর দশকের মাঝামাঝি থেকে বড় সাইটগুলো SVG আইকনে সরে যায় — যেমন GitHub ২০১৬ সালে তাদের Octicons-কে font থেকে SVG-তে নিয়ে যায়। তবে icon font হারিয়ে যায়নি। Font Awesome এখন একই আইকনের font আর SVG — দুই সংস্করণই দেয়। আর Google-এর Material Symbols একটি variable font — পুরুত্ব, ভরাট আর মাপ font-এর অক্ষ দিয়ে মসৃণভাবে বদলানো যায়। এই সাইটটিও (ABCL TECH) পাতার ছোট আইকনগুলোর জন্য Font Awesome-এর web font ব্যবহার করে, প্রতিটিতে aria-hidden="true" দিয়ে — যেমন এই পাতার শিরোনামের পাশের আইকনগুলো। অর্থাৎ icon font সঠিক নিয়ম মেনে ব্যবহার করলে কাজ চলে; শুধু নতুন প্রজেক্টে SVG বেশি নিয়ন্ত্রণ আর কম ঝুঁকি দেয়।
আইকন লাইব্রেরি — নিজে না এঁকে
প্রতিটি আইকন নিজে আঁকার দরকার নেই। icon library একই নকশা-নিয়মে আঁকা শত-হাজার আইকন দেয় — সব আইকনের মাপ, রেখার পুরুত্ব আর কোণের ধরন মিলে থাকে, তাই পাতা পরিপাটি দেখায়:
Lucide
পুরোনো Feather Icons-এর community-চালিত উত্তরসূরি। ২৪×২৪ খাতায় রেখা-ভিত্তিক (stroke) আইকন, তাই stroke-width বদলে হালকা-ভারী করা যায়।
Heroicons
Tailwind CSS-এর নির্মাতাদের বানানো; outline আর solid দুই ধরনে। কোড কপি করলেই inline SVG.
open sourceMaterial Symbols
Google-এর আইকন — variable font হিসেবে, আবার SVG হিসেবেও পাওয়া যায়। Android-এর চেনা চেহারা।
font + SVGFont Awesome
সবচেয়ে পুরোনো আর বড় সংগ্রহের একটি; ফ্রি আর Pro সংস্করণ। web font, SVG আর sprite — সব রূপে।
font + SVGযেটিই বেছে নিন, লাইসেন্স দেখে নিন, আর পুরো লাইব্রেরি না নামিয়ে শুধু দরকারি আইকনগুলো নিন — দশটি আইকনের জন্য হাজার আইকনের ফাইল মানে ক্রেতার মোবাইল ডেটা অপচয়।
SVGO — ফাইল ছোট করা
Illustrator বা Figma থেকে export করা SVG-তে অনেক বাড়তি জিনিস থাকে: সম্পাদকের নিজস্ব তথ্য (metadata), মন্তব্য, খালি গ্রুপ, আর 12.000003-এর মতো অপ্রয়োজনীয় দশমিক। SVGO (Node.js-এ চলা একটি টুল) এগুলো ছেঁটে প্রায়ই ফাইলের আকার অর্ধেক বা তারও কম করে; ব্রাউজারে চালানোর রূপ SVGOMG. দুটি সতর্কতা: অপ্টিমাইজ করার পরে ছবিটি একবার চোখে দেখে নিন, আর viewBox ও <title> রয়ে গেছে কি না দেখুন — SVGO-র পুরোনো সংস্করণের ডিফল্ট সেটিং viewBox মুছে ফেলত, যা ছবিকে আর রেসপন্সিভ রাখে না। এ ছাড়া server-এ gzip বা Brotli চালু থাকলে লেখা-ভিত্তিক SVG আরও অনেক ছোট হয়ে পৌঁছায়।
নিরাপত্তা — SVG ছবি, আবার ডকুমেন্টও
SVG ফাইলের ভেতরে <script>, onload="…"-এর মতো event attribute, এমনকি <foreignObject> দিয়ে HTML-ও রাখা যায়। কেউ আপনার সাইটে “প্রোফাইল ছবি” হিসেবে এমন SVG আপলোড করল, আর আপনি সেটি inline বসালেন বা সরাসরি আপনার ডোমেইনে খোলার সুযোগ দিলেন — তাহলে তার script আপনার সাইটের ভেতরে চলবে। একে বলে XSS (cross-site scripting), যা দিয়ে ব্যবহারকারীর লগইন সেশন চুরি পর্যন্ত সম্ভব। নিয়ম: (১) অচেনা উৎসের SVG কখনো inline বসাবেন না, innerHTML দিয়েও না; (২) দেখাতে হলে <img> দিয়ে দেখান — সেখানে script চলে না; (৩) inline বসানো একান্তই দরকার হলে DOMPurify-এর মতো পরীক্ষিত লাইব্রেরি দিয়ে sanitize করুন; (৪) আপলোড করা ফাইল সম্ভব হলে আলাদা ডোমেইন থেকে পরিবেশন করুন। SVGO ফাইল ছোট করে, নিরাপদ করে না — এটি sanitizer নয়।
আরও গভীরে: SVG-র ইতিহাস একটি আপসের গল্প। ১৯৯৮ সালে W3C-তে দুটি প্রতিদ্বন্দ্বী vector ভাষার প্রস্তাব জমা পড়ে — Microsoft-সহ কয়েকটি কোম্পানির VML, আর Adobe, IBM, Netscape, Sun-এর PGML. W3C দুটির কোনোটিকেই বেছে না নিয়ে নতুন দল গঠন করে, যার ফল SVG 1.0 (W3C Recommendation, ২০০১)। ব্রাউজারের ভেতরে SVG আঁকার কাজ হয় পর্ব ০১-এর সেই paint ধাপে: path-কে রেখা আর বাঁকের গাণিতিক বর্ণনা থেকে pixel-এ রূপান্তর (rasterize), যেখানে anti-aliasing ধারকে মসৃণ দেখায়। এজন্যই shape-rendering="crispEdges" দিলে (ছবি ৪৪.১-এর বাঁয়েরটির মতো) ব্রাউজার মসৃণ করা বন্ধ করে ধারালো pixel-প্রান্ত দেখায়। আর CSS transform SVG-র আকারে দিলে ডিফল্ট ঘোরার কেন্দ্র আকারের মাঝখান নয়, SVG-র (0,0) — transform-box: fill-box; transform-origin: center; দিলে তবেই নিজের মাঝখান ঘিরে ঘোরে।
পরীক্ষা ও ইন্টারভিউতে — বিশ্ববিদ্যালয়, চাকরি বা ফ্রন্ট-এন্ড ইন্টারভিউর পরীক্ষায় এ ধরনের প্রশ্ন প্রায়ই আসে:
- Raster আর vector ছবির পার্থক্য কী? SVG কোনটি? — raster হলো pixel-এর গ্রিড, বড় করলে ঝাপসা; vector হলো আঁকার নির্দেশ, যেকোনো মাপে ঝকঝকে। SVG হলো XML-ভিত্তিক vector ফরম্যাট।
viewBox-এর চারটি সংখ্যার অর্থ কী? —min-x min-y width height: খাতার কোন অংশ দেখানো হবে; width/height attribute-এর সাথে মিলিয়ে scale ঠিক হয়।- SVG আইকন কীভাবে লেখার রং নেয়? —
fillবাstroke-এcurrentColor; আইকন তখন বাবা-মায়েরcolorঅনুসরণ করে। - শুধু আইকনের একটি বাটন কীভাবে অ্যাক্সেসিবল করবেন? — বাটনে
aria-label(বা visually-hidden লেখা), ভেতরের svg-তেaria-hidden="true". - Icon font-এর চেয়ে SVG আইকন কেন ভালো ধরা হয়? — screen reader-এর ভুল পড়া নেই, font না এলে ভাঙে না, আঁকা ধারালো, বহু রং আর অ্যানিমেশন সম্ভব, শুধু দরকারি আইকন পাঠানো যায়।
১০ · AI-এর যুগে — AI-এর আঁকা SVG আর আইকন-কোড যাচাই
AI খুব সহজে SVG লিখে দেয় — “একটি শাপলার লোগো দাও” বললেই কয়েক সেকেন্ডে কোড। কিন্তু AI আসলে ছবিটি দেখে না; সে সংখ্যার একটি সম্ভাব্য সারি লেখে। ফলে পাপড়ি বেঁকে যায়, বৃত্ত পতাকার বাইরে চলে যায়, আর অ্যাক্সেসিবিলিটির নিয়ম প্রায়ই বাদ পড়ে। AI-এর দেওয়া SVG তাই সবসময় ব্রাউজারে খুলে চোখে দেখে, তারপর markup পড়ে যাচাই করতে হয়।
| AI যা দিতে পারে | সমস্যা | ঠিক কী |
|---|---|---|
viewBox নেই, শুধু width="500" height="500" | ছোট-বড় হয় না, মোবাইলে পাতার বাইরে চলে যায় | viewBox রাখুন, মাপ CSS-এ |
xlink:href আর xmlns:xlink | পুরোনো রীতি | সাধারণ href |
আইকনে fill="#333333" হার্ডকোড | hover, ডার্ক মোড, high contrast-এ রং মেলে না | fill="currentColor" |
আইকন-বাটনে কোনো নাম নেই, বা পাশে লেখা থাকা আইকনে role="img" | screen reader নীরব, বা একই কথা দুবার | বাটনে aria-label, সাজের আইকনে aria-hidden="true" |
<i class="fa …"> কিন্তু aria-hidden নেই | অর্থহীন অক্ষর পড়া হতে পারে | aria-hidden="true" + আলাদা লেখা |
ব্যবহারকারীর SVG innerHTML দিয়ে বসানো | XSS-এর ঝুঁকি | <img> বা DOMPurify |
| হাজার দশমিক-ভরা বিশাল path, অ্যানিমেশনে reduced motion নেই | ভারী ফাইল, অস্বস্তিকর নড়াচড়া | SVGO, prefers-reduced-motion |
AI-কে SVG-র কাজ দেওয়ার সময় প্রম্পটেই আধুনিক নিয়মগুলো দাবি করুন, আর কোডের সাথে ব্যাখ্যা চান — যাতে আপনি প্রতিটি সংখ্যার মানে মিলিয়ে নিতে পারেন:
AI-এর দেওয়া SVG হাতে পেলে — যাচাইয়ের চেকলিস্ট
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন। এগুলো আপনাকে শুধু ট্যাগ নয়, ওয়েবের গ্রাফিক্স-জগতের সিদ্ধান্তগুলো বুঝতে সাহায্য করবে।
প্র ০১SVG ২০০১ সালেই W3C-র মান হয়ে গেল, অথচ ওয়েবে সবখানে ছড়াতে প্রায় এক দশক লাগল কেন?
কারণ একটি ভালো মান থাকা আর সবার ব্রাউজারে সেটি চলা — দুটি আলাদা জিনিস। এই দেরির পেছনে তিনটি বড় শক্তি কাজ করেছে।
- সবচেয়ে বড় ব্রাউজার রাজি ছিল না: ২০০০-এর দশকে বেশিরভাগ মানুষ Internet Explorer ব্যবহার করতেন। Microsoft-এর নিজস্ব vector ভাষা VML ছিল — যে প্রস্তাব W3C SVG-র পক্ষে বাদ দিয়েছিল। IE দীর্ঘদিন SVG চেনেনি; প্রথম সাপোর্ট আসে IE9-এ, ২০১১ সালে। যতদিন অর্ধেকের বেশি দর্শক SVG দেখতে পায় না, ততদিন কোনো ব্যবসা এর ওপর ভরসা করে না।
- Flash ছিল সহজ বিকল্প: vector অ্যানিমেশন, খেলা, ইন্টারঅ্যাকটিভ ব্যানার — সব Adobe Flash plugin দিয়ে হতো, প্রায় সব কম্পিউটারে চলত। কিন্তু ২০০৭-এ আসা iPhone Flash চালায়নি, আর ২০১০ সালে Steve Jobs-এর খোলা চিঠি “Thoughts on Flash” মোবাইলে Flash-এর পথ প্রায় বন্ধ করে দেয়। মোবাইল ওয়েবে vector-এর একমাত্র উন্মুক্ত পথ রইল SVG; আর ২০২০ সালের শেষে Adobe Flash Player-এর সমর্থনই বন্ধ করে দেয়।
- HTML-এর ভেতরে লেখা যেত না: শুরুতে SVG-কে HTML পাতায় সরাসরি লিখতে হলে পাতাটিকে কড়া XHTML হিসেবে পাঠাতে হতো — একটি ভুলেই পুরো পাতা ভেঙে যেত। HTML5-এর নতুন parser নিয়ম SVG-কে সাধারণ HTML-এর ভেতরে লেখার সুযোগ দেয় — আজকের inline SVG সেখান থেকেই।
এর সাথে যোগ হলো পর্দার বিপ্লব। ২০১০-এর দিকে উচ্চ-ঘনত্বের (“Retina”) পর্দা আসায় একই PNG আইকন দুই-তিন মাপে বানাতে হতো; vector-এর এক ফাইলের সুবিধা হঠাৎ খুব বাস্তব হয়ে উঠল। বাংলাদেশে সস্তা Android ফোন থেকে বড় মনিটর পর্যন্ত নানা পর্দার কারণে এই সুবিধা আজ আরও বেশি।
মূল উপলব্ধি: ওয়েবে প্রযুক্তি জেতে শুধু ভালো হওয়ার জোরে নয় — ব্রাউজার-বাজার, ব্যবসার স্বার্থ আর নতুন যন্ত্রের চাপ মিলে ঠিক করে কখন একটি মান সত্যিই ব্যবহারযোগ্য হবে। আজ নতুন CSS ফিচারের Baseline দেখার অভ্যাসও সেই একই শিক্ষার ফল।
প্র ০২Icon font এত জনপ্রিয় হয়েও বড় সাইটগুলো SVG-তে সরে গেল কেন? তাহলে কি icon font ব্যবহার করা ভুল?
Icon font জনপ্রিয় হয়েছিল তার সময়ের সমস্যা মেটাতে। ২০১০-এর শুরুতে Internet Explorer-এর পুরোনো সংস্করণ তখনো অনেকের কম্পিউটারে, যেখানে SVG চলে না; প্রতিটি আইকন আলাদা PNG মানে আলাদা HTTP request, আর Retina পর্দার জন্য প্রতিটির দুই মাপ। একটি font ফাইলে শত আইকন, CSS-এর color দিয়ে রং বদল — চমৎকার সমাধান মনে হয়েছিল। Font Awesome-এর মতো লাইব্রেরি এক লাইনে আইকন বসানো সহজ করে দিল।
কিন্তু font আসলে লেখার জন্য তৈরি, ছবির জন্য নয় — অংশ ৯-এর সমস্যাগুলো (অর্থহীন অক্ষর, font আটকে গেলে ফাঁকা বাক্স, লেখার মতো ঝাপসা আঁকা) এই অমিল থেকেই। অফিসের firewall বা ad-blocker font আটকে দিলেও একই বিপদ। এসব কারণে ২০১৪-১৬ সালের দিকে বেশ কিছু বড় দল প্রকাশ্যে SVG-তে যাওয়ার কারণ লিখেছিল; GitHub ২০১৬ সালে তাদের Octicons-কে font থেকে SVG-তে সরায়। Font Awesome নিজেও পরের সংস্করণগুলোতে SVG রূপ যোগ করে।
তাহলে কি icon font ভুল? না — এটি একটি trade-off. ঠিকভাবে ব্যবহার করলে (প্রতিটি আইকনে aria-hidden="true", অর্থ বোঝাতে আলাদা লেখা, font-display বিবেচনা) এটি কাজ করে। এই সাইটটিও শিরোনামের ছোট সাজের আইকনে Font Awesome-এর web font ঠিক এভাবে ব্যবহার করে। Google-এর Material Symbols variable font-এর অক্ষ দিয়ে এক ফাইলে হাজার রকম পুরুত্ব-ভরাট দেয় — যা SVG-তে আলাদা ফাইল ছাড়া কঠিন। তবে নতুন প্রজেক্টে, বিশেষ করে যেখানে আইকন অর্থ বহন করে, SVG কম ঝুঁকির পথ।
মূল উপলব্ধি: প্রযুক্তির “ফ্যাশন” বদলায় কারণ সমস্যা বদলায়। IE-র যুগের সেরা সমাধান আজ দ্বিতীয় পছন্দ। প্রশ্ন করুন: এই সমাধানটি কোন সমস্যার জন্য বানানো হয়েছিল, আর সেই সমস্যা কি আজও আছে?
প্র ০৩একটি সাইটে ৮০টি আইকন — inline sprite, আলাদা sprite ফাইল, নাকি প্রতিটি আলাদা <img>? কীভাবে সিদ্ধান্ত নেবেন?
এটি একটি পারফরম্যান্স ও রক্ষণাবেক্ষণের প্রশ্ন, আর উত্তর নির্ভর করে আইকনগুলো কতবার, কোথায়, কীভাবে ব্যবহার হয় তার ওপর। তিনটি পথের হিসাব:
- Inline sprite (পাতার ভেতরে
<symbol>): কোনো বাড়তি request নেই, আইকন সঙ্গে সঙ্গে দেখা যায়, currentColor পুরোপুরি কাজ করে। কিন্তু প্রতিটি পাতার HTML-এ ৮০টি আইকনের কোড — হয়তো ২০-৩০ KB — প্রতিবার নামে, cache হয় না। পাতায় যদি মাত্র ৫টি আইকন লাগে, বাকি ৭৫টি অপচয়। - আলাদা sprite ফাইল (
<use href="/icons.svg#cart">): একবার নামলে browser cache থেকে আসে, HTML হালকা থাকে, currentColor-ও চলে। শর্ত — একই origin থেকে পরিবেশন। প্রথমবার ফাইলটি না আসা পর্যন্ত আইকন ফাঁকা থাকে। - প্রতিটি আলাদা
<img>: সবচেয়ে সরল আর নিরাপদ, প্রতিটি আলাদাভাবে cache. HTTP/2 আর HTTP/3-এ অনেক ছোট request আগের মতো ব্যয়বহুল নয়। কিন্তু currentColor চলে না — hover-এ রং বদলাতে আলাদা ফাইল বা CSS mask লাগে।
বাস্তবে যা দেখা যায়: React বা Vue-এর মতো framework-এ প্রায়ই প্রতিটি আইকন একটি ছোট component — build tool শুধু ব্যবহৃত আইকনগুলোকেই চূড়ান্ত কোডে রাখে (tree-shaking), আর সেগুলো inline SVG হিসেবে বসে। সাধারণ static সাইটে (এই কোর্সের মতো cPanel-এ রাখা সাইট) আলাদা sprite ফাইল প্রায়ই সেরা ভারসাম্য। লোগো আর বড় ইলাস্ট্রেশন — <img>.
একটি সূক্ষ্ম বিষয়: <use>-এর shadow tree-তে পাতার CSS selector পৌঁছায় না, কিন্তু CSS variable পৌঁছায়। তাই দুই-রঙা আইকন চাইলে symbol-এর ভেতরে fill="var(--icon-accent, currentColor)" লিখে বাইরে থেকে --icon-accent দিন — sprite-এর সুবিধা থাকল, রঙের নমনীয়তাও।
মূল উপলব্ধি: পারফরম্যান্সের সিদ্ধান্তে “সবসময় সেরা” বলে কিছু নেই — আছে মাপজোখ। DevTools-এর Network প্যানেলে কত KB, কতগুলো request, প্রথম দেখা কখন — এগুলো দেখে সিদ্ধান্ত নিন, অনুমানে নয়।
প্র ০৪একটি “ছবি” কীভাবে আক্রমণের হাতিয়ার হয়? SVG আপলোডের সুযোগ দেওয়া সাইট কীভাবে নিজেকে রক্ষা করবে?
JPEG বা PNG নিছক pixel-এর তথ্য — ব্রাউজার শুধু রং পড়ে। কিন্তু SVG একটি পূর্ণ XML ডকুমেন্ট, আর SVG-র নিয়মে <script>, onload-এর মতো event attribute, অন্য ফাইলের লিংক, এমনকি <foreignObject>-এর ভেতরে HTML রাখা বৈধ। অর্থাৎ “ছবি” নামের ফাইলটি আসলে একটি ছোট ওয়েব পাতাও হতে পারে।
আক্রমণটি কেমন: ধরুন একটি ফ্রিল্যান্সিং মার্কেটপ্লেস ব্যবহারকারীদের প্রোফাইল ছবি হিসেবে SVG নেয়। আক্রমণকারী এমন একটি SVG আপলোড করল, যার ভেতরে script আছে। সাইট যদি ফাইলটি নিজের ডোমেইনে রাখে আর কেউ সরাসরি সেই URL খোলে, অথবা সাইট সেটি inline বসায়, তাহলে script চলবে সাইটের নিজের origin-এ — ব্যবহারকারীর সেশন, পাতার তথ্য, সব তার নাগালে। এটি stored XSS — একবার আপলোড, অনেকের ক্ষতি।
রক্ষার স্তর:
- দেখানোর পদ্ধতি:
<img>বা CSS background-এ SVG-র script চলে না, বাইরের ফাইলও লোড হয় না — তাই প্রদর্শনের জন্য এটাই প্রথম ঢাল। - পরিশোধন: inline দরকার হলে DOMPurify-এর মতো পরীক্ষিত sanitizer দিয়ে script ও event attribute ছেঁকে ফেলুন। নিজে regex লিখে ছাঁকা বিপজ্জনক — আক্রমণকারীরা অসংখ্য ফাঁক জানে।
- পরিবেশন: আপলোড করা ফাইল আলাদা ডোমেইন থেকে দিন (অনেক বড় সাইট তাই করে),
Content-Security-Policyheader দিয়ে script বন্ধ রাখুন, প্রয়োজনেContent-Disposition: attachmentদিয়ে ব্রাউজারকে “খুলো না, ডাউনলোড করো” বলুন। - server-এর দিক: server যদি SVG-কে PNG-তে রূপান্তর করে, তার XML parser-কেও বাইরের entity লোড করতে না দেওয়ার মতো নিরাপদ সেটিংয়ে রাখতে হয় — নইলে server-এর ফাইল পড়ার মতো আক্রমণের ঝুঁকি থাকে।
মূল উপলব্ধি: নিরাপত্তায় ফাইলের নাম বা extension নয়, দেখতে হয় ফাইলটি কী করতে পারে। SVG-র শক্তি (DOM, script, interactivity) আর তার ঝুঁকি একই মুদ্রার দুই পিঠ। “বাইরে থেকে আসা সবকিছু অবিশ্বস্ত” — এই নীতি HTML, SVG, এমনকি AI-এর দেওয়া কোডের বেলাতেও খাটে।
প্র ০৫Vector সবসময় raster-এর চেয়ে ভালো? কখন SVG ভুল পছন্দ — আর canvas কোথায় আসে?
না। SVG চমৎকার যখন ছবিটি সহজে বর্ণনা করা যায় — কয়েকটি আকার, রেখা, সমতল রং। কিন্তু প্রতিটি ছবি এমন নয়।
- ফটো: একটি ফটোতে প্রতিটি pixel-এ আলাদা রং, আলো-ছায়া, কুয়াশা। এটিকে vector-এ লিখতে গেলে হাজার হাজার আকার লাগবে, আর ফাইল হবে একই মানের WebP বা AVIF-এর চেয়ে বহুগুণ বড় — তবু দেখতে খারাপ। ফটোর জন্য raster-ই ঠিক।
- অতি জটিল ইলাস্ট্রেশন: হাজার হাজার node-এর SVG মানে DOM-এ হাজার হাজার element; প্রতিটি স্ক্রল বা অ্যানিমেশনে ব্রাউজারকে সব নতুন করে হিসাব করতে হতে পারে, সস্তা মোবাইলে পাতা ধীর হয়। তখন একই ছবি একটি অপ্টিমাইজ করা raster হলে দ্রুত।
- বিশাল ডেটার চার্ট: D3.js-এর মতো লাইব্রেরি SVG দিয়ে চমৎকার চার্ট বানায় — প্রতিটি বার বা বিন্দু একটি element, তাই hover, tooltip, অ্যাক্সেসিবিলিটি সহজ। কিন্তু এক লাখ বিন্দুর scatter plot-এ এক লাখ DOM element অসহনীয়। তখন আসে
<canvas>: JavaScript সরাসরি pixel আঁকে, DOM-এ একটিই element.
এখানে একটি মৌলিক নকশা-পার্থক্য আছে। SVG হলো retained mode — ব্রাউজার প্রতিটি আকার মনে রাখে, আপনি একটি বৃত্তের রং বদলালে বাকি সব নিজেই সামলায়। Canvas হলো immediate mode — আঁকা হয়ে গেলে শুধু pixel থাকে, কিছু বদলাতে হলে পুরো ছবি নিজে আবার আঁকতে হয়, আর screen reader-এর জন্য আলাদা ব্যবস্থা লাগে। খেলা, ছবি সম্পাদনা বা বিশাল ডেটায় canvas (বা WebGL), সাধারণ আইকন-লোগো-চার্টে SVG.
একটি বাস্তব কৌশল: অনেক মানচিত্র-অ্যাপ দুটোই মেশায় — ভারী ভূমি-নকশা canvas বা টালি-ছবিতে, আর তার ওপরে ক্লিকযোগ্য পিন আর লেবেল SVG বা HTML-এ।
মূল উপলব্ধি: ফরম্যাট বাছাই আসলে প্রশ্ন করা — “ছবিটির তথ্য কোন রূপে সবচেয়ে সংক্ষেপে আর সবচেয়ে কাজের ভাবে লেখা যায়?” আকারে বর্ণনাযোগ্য হলে vector, pixel-এ সমৃদ্ধ হলে raster, বিশাল আর দ্রুত বদলালে canvas.
অনুশীলন
উত্তর দেখার আগে নিজে হিসাব করুন বা ওপরের যেকোনো লাইভ এডিটরে লিখে দেখুন।
-
viewBox-এর হিসাব:
<svg width="300" height="150" viewBox="0 0 100 50">-এর ভেতরে<circle cx="50" cy="25" r="10">. (ক) পর্দায় বৃত্তের কেন্দ্র কোথায়, ব্যাসার্ধ কত pixel? (খ) viewBox-কে"50 0 100 50"করলে বৃত্তটি কোথায় যাবে?(ক) scale = ৩০০ ÷ ১০০ = ৩ (উচ্চতাতেও ১৫০ ÷ ৫০ = ৩, অনুপাত মেলে)। কেন্দ্র (৫০×৩, ২৫×৩) = (১৫০, ৭৫) pixel — ঠিক মাঝখানে; ব্যাসার্ধ ১০×৩ = ৩০ pixel.
(খ) জানালা এখন x = ৫০ থেকে শুরু, তাই বৃত্তের কেন্দ্র (৫০ − ৫০)×৩ = ০ — একেবারে বাঁ কিনারায়। বৃত্তের ডান অর্ধেক দেখা যাবে, বাঁ অর্ধেক ফ্রেমের বাইরে।
-
নিজের path: ২৪×২৪ খাতায় একটি “ঠিক চিহ্ন” (✓) আর একটি ডানমুখী তীর (→) আঁকুন — শুধু M আর L (বা H) দিয়ে,
stroke="currentColor"আর গোল মাথাসহ।একটি সম্ভাব্য উত্তর (অন্য সংখ্যাও ঠিক হতে পারে, শুধু ছবিটি চেনা যাওয়া চাই):
<svg viewBox="0 0 24 24" width="48" height="48" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M 4 12 L 10 18 L 20 6"/> </svg> <svg viewBox="0 0 24 24" width="48" height="48" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"> <path d="M 4 12 H 20 M 14 6 L 20 12 L 14 18"/> </svg>তীরে দুটি M — একটি দণ্ড, একটি মাথা; এক path-এ দুই টুকরো।
fill="none"না দিলে খোলা রেখার ভেতরে কালো ভরাট দেখা যেত। -
অ্যাক্সেসিবিলিটি নিরীক্ষা: তিনটি ক্ষেত্রে কী markup দেবেন — (ক) “PDF ডাউনলোড” লেখার পাশে একটি ডাউনলোড-আইকন; (খ) মোবাইল মেনুর তিন-দাগের (☰) বাটন, কোনো লেখা নেই; (গ) একটি SVG বার-চার্ট, যা জেলাভিত্তিক বিক্রি দেখায়।
(ক) লেখা অর্থ বহন করছে, আইকন শুধু সাজ:
<svg aria-hidden="true">.(খ)
<button aria-label="মেনু খুলুন" aria-expanded="false">, ভেতরের svg-তেaria-hidden="true". মেনু খুললে JavaScriptaria-expanded-কেtrueকরবে (পর্ব ১২)।(গ) চার্ট অর্থবহ ছবি:
<svg role="img" aria-labelledby="c-title"><title id="c-title">জেলাভিত্তিক বিক্রি: ঢাকা সর্বোচ্চ…</title>. চার্টের আসল সংখ্যাগুলো পাশে একটি HTML টেবিলে বা লেখায় দেওয়া আরও ভালো — শুধু ছবির নাম দিয়ে সব তথ্য বলা যায় না। -
Export করা SVG পরিষ্কার করা: একটি ডিজাইন টুল থেকে আসা লোগোতে আছে:
<?xml …?>ঘোষণা, সম্পাদকের metadata,id="Layer_1",style="fill:#006A4E",width="512px" height="512px", viewBox, আর<title>. Inline আইকন হিসেবে ব্যবহারের আগে কোনগুলো রাখবেন, কোনগুলো বদলাবেন বা মুছবেন?মুছুন:
<?xml …?>(inline-এ অপ্রয়োজনীয়), সম্পাদকের metadata, অপ্রয়োজনীয়id="Layer_1"(একই পাতায় একাধিক SVG-তে একই id হলে সংঘাত হয়)।বদলান:
style="fill:#006A4E"-কেfill="currentColor"(একরঙা আইকন হলে) — inline style CSS-কে হারিয়ে দেয়, তাই এটি রেখে দিলে আপনার CSS কাজ করবে না।width="512px" height="512px"-কে ছোট মাপে (যেমন24) বা CSS-এ।রাখুন: viewBox (না থাকলে ছোট-বড় হবে না), আর অর্থবহ লোগো হলে
<title>+role="img". এই কাজের বেশিরভাগ SVGO/SVGOMG স্বয়ংক্রিয়ভাবে করে — তবে viewBox আর title রয়ে গেল কি না নিজে দেখে নিন।
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমSVG রেখা “নিজে আঁকা হওয়ার” অ্যানিমেশন বানানোর ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- path-এ
pathLength="100"দিয়ে দৈর্ঘ্য ১০০ ধরা stroke-dasharray: 100— পুরো রেখা একটি দাগstroke-dashoffset: 100— দাগ সরিয়ে রেখা অদৃশ্য@keyframes-এ offset ০ পর্যন্ত animationprefers-reduced-motion-এ animation বন্ধ, offset ০
<svg width="200" height="100" viewBox="0 0 100 50">-এর ভেতরে খাতার এক ঘর (user unit) পর্দায় কত বড় দেখাবে?
- 1px
- 2px
- 0.5px
- হিসাব করা যায় না, ব্রাউজারের ওপর নির্ভর করে
“PDF ডাউনলোড” লেখার পাশে একটি সাজের ডাউনলোড-আইকন (inline SVG). screen reader-এর জন্য সঠিক markup কোনটি?
- svg-তে
role="img" aria-label="ডাউনলোড আইকন" - svg-এর ভেতরে
<title>ডাউনলোড</title> - svg-তে
aria-hidden="true" - svg-তে
alt="ডাউনলোড"
কোন উপায়ে পাতায় বসানো SVG-র ভেতরের আকারের fill পাতার CSS দিয়ে বদলানো যায়?
- Inline
<svg>হিসেবে HTML-এর ভেতরে লিখলে <img src="icon.svg">দিয়ে- CSS
background-imageদিয়ে <object data="icon.svg">দিয়ে
pathLength="100" দেওয়া একটি path-এ stroke-dasharray: 100; stroke-dashoffset: 100; দিলে কী দেখা যাবে?
- পুরো রেখা
- রেখার অর্ধেক
- ছোট ছোট দাগ-ফাঁক
- কিছুই না — রেখা অদৃশ্য
Icon font-এর একটি পরিচিত অ্যাক্সেসিবিলিটি সমস্যা কোনটি?
- CSS-এর
colorদিয়ে আইকনের রং বদলানো যায় না - screen reader আইকনের জায়গায় অর্থহীন অক্ষর বা লুকানো শব্দ পড়তে পারে
- আইকনের মাপ font-size দিয়ে বদলানো যায় না
- কোনো আধুনিক ব্রাউজার icon font দেখাতে পারে না
একটি সাইট ব্যবহারকারীদের SVG প্রোফাইল ছবি আপলোড করতে দেয়। সেগুলো দেখানোর সবচেয়ে নিরাপদ সাধারণ উপায় কোনটি?
- ফাইলের লেখা পড়ে
innerHTMLদিয়ে পাতায় বসানো - SVGO দিয়ে ছোট করে inline বসানো
<img src="…">দিয়ে দেখানো- ফাইলের নাম
.pngকরে দেওয়া
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- SVG হলো XML-এ লেখা আঁকার নির্দেশ — যেকোনো মাপে ঝকঝকে, ছোট ফাইল, আর inline হলে পুরোটাই DOM.
- viewBox খাতার অংশ বাছে, width/height ফ্রেমের মাপ দেয়; অনুপাত না মিললে preserveAspectRatio (meet / slice / none).
- path-এর কমান্ড: M, L, H, V, Q, C, A, Z — বড় হাতের absolute, ছোট হাতের relative; রেখা সাজায় stroke-এর পরিবার, আর dasharray + dashoffset দিয়ে রেখা আঁকার অ্যানিমেশন (reduced motion মেনে)।
- <symbol> + <use> দিয়ে sprite, currentColor দিয়ে লেখার রঙে আইকন; সাজের আইকনে aria-hidden="true", একা আইকনের বাটনে aria-label, অর্থবহ ছবিতে role="img" + নাম।
- লোগো-ইলাস্ট্রেশন <img>-এ, আইকন inline/sprite-এ; SVGO দিয়ে ছোট করুন, আর অচেনা SVG কখনো inline নয় — XSS-এর ঝুঁকি।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ৪৫ · অ্যাক্সেসিবল CSS — focus, contrast, reduced motion আর বড় লেখাপরবর্তী পর্বসবার জন্য ব্যবহারযোগ্য নকশার CSS-দিক।
- HTML ও CSS · কোর্স হোম৫৯টি পর্বপুরো কোর্সের রোডম্যাপ — কোন পর্ব কখন।
- পর্ব ০৬ · ছবি, অডিও, ভিডিও আর iframeফিরে দেখুনraster বনাম vector, ছবির ফরম্যাট আর alt লেখার নিয়ম।
- পর্ব ১২ · অ্যাক্সেসিবিলিটি আর ARIAফিরে দেখুনaccessible name, aria-hidden আর ARIA-র প্রথম নিয়ম।
- JavaScript · DOM-এর ভিত্তিপাশের ট্র্যাকinline SVG-র আকার JavaScript দিয়ে খুঁজে বদলানো।