Shadow (ছায়া) — মোবাইল ইন্টারফেসে একটি ভিজ্যুয়াল ইফেক্ট যা উপাদানগুলির মধ্যে গভীরতা এবং শ্রেণিবিন্যাসের বিভ্রম সৃষ্টি করে। ছায়াগুলি দেখায় কোন উপাদান z-সমতলে উপরে রয়েছে এবং তাই আরও গুরুত্বপূর্ণ বা ইন্টারঅ্যাকটিভ। Material Design Guidelines (Google, 2026) অনুসারে, সিস্টেম ছায়াগুলি পাঁচটি মূল উচ্চতা (elevation) ব্যবহার করে: 0 dp (সমতল), 1–4 dp (বাটন), 6–12 dp (কার্ড), 16–24 dp (ডায়ালগ), 24+ dp (মোডাল উইন্ডো)। উপাদানের উচ্চতা সম্পর্কে আরও জানতে Elevation সম্পর্কে নিবন্ধটি পড়ুন।
মূল বিষয়
ছায়া (shadow) ইউজার ইন্টারফেসে একটি ভিজ্যুয়াল ইফেক্ট যা আলো এবং গভীরতা অনুকরণ করে। একটি উপাদানের একটি গাঢ় ঝাপসা কপি এঁকে ছায়া তৈরি করা হয়, যা মূল থেকে সরে যায়। মোবাইল ডিজাইনে, ছায়া তিনটি কাজ করে: শ্রেণিবিন্যাস দেখায় (উপরে থাকা উপাদান = লম্বা ছায়া), ইন্টারঅ্যাকটিভিটির সংকেত দেয় (ছায়া সহ বাটনগুলি চাপার মতো দেখায়), বিষয়বস্তুকে পটভূমি থেকে আলাদা করে (ছায়া সহ কার্ডগুলি আলাদা ব্লক হিসাবে পড়া যায়)।
Google-এর Material Design-এ, ছায়াগুলি elevation ধারণার সাথে অঙ্গাঙ্গীভাবে জড়িত। প্রতিটি উপাদান z-স্থানাঙ্কে একটি নির্দিষ্ট উচ্চতা দখল করে এবং ছায়া হল উপরের আলোর প্রক্ষেপণ। Apple-এর Human Interface Guidelines একটি কঠোর উচ্চতা ব্যবস্থা নির্ধারণ করে না, তবে ইন্টারফেসে ভিজ্যুয়াল শ্রেণিবিন্যাস এবং গভীরতা তৈরি করতে ছায়া ব্যবহারের সুপারিশ করে।
Nielsen Norman Group-এর একটি গবেষণা (2024) অনুসারে, সঠিকভাবে স্থাপিত ছায়াগুলি একটি ইন্টারঅ্যাকটিভ উপাদান খুঁজে পেতে সময় 24% কমিয়ে দেয়। ছায়াগুলি দৃষ্টি প্রতিবন্ধী ব্যবহারকারীদের উপাদানের সীমানা পার্থক্য করতেও সাহায্য করে। তবে, ছায়ার অত্যধিক ব্যবহার (স্ক্রিনে 3+ স্তর) জ্ঞানীয় ভার বৃদ্ধি করে এবং ধারণাকে খারাপ করে।
iOS-এ, ছায়াগুলি CALayer বৈশিষ্ট্যের মাধ্যমে বাস্তবায়িত হয়: shadowColor ছায়ার রঙ সেট করে, shadowOffset — CGSize-এ (x, y) সরণ, shadowRadius — ঝাপসা ব্যাসার্ধ, shadowOpacity — 0 থেকে 1 পর্যন্ত অস্বচ্ছতা। কর্মক্ষমতার জন্য, shadowPath — একটি UIBezierPath যা ছায়ার আকৃতি বর্ণনা করে — সেট করারও সুপারিশ করা হয়, যাতে Core Animation এটি স্বয়ংক্রিয়ভাবে গণনা না করে।
// UIKit: CALayer-এর মাধ্যমে ছায়া কনফিগারেশন
import UIKit
let cardView = UIView()
cardView.backgroundColor = .systemBackground
cardView.layer.cornerRadius = 12
// ছায়া কনফিগারেশন
cardView.layer.shadowColor = UIColor.black.cgColor
cardView.layer.shadowOpacity = 0.15
cardView.layer.shadowOffset = CGSize(width: 0, height: 4)
cardView.layer.shadowRadius = 8
"> অপ্টিমাইজেশন: স্পষ্ট shadowPath
cardView.layer.shadowPath = UIBezierPath(
roundedRect: cardView.bounds,
cornerRadius: 12
).cgPath
SwiftUI-এ, ছায়াগুলি .shadow() মডিফায়ারের মাধ্যমে color, radius, x, y প্যারামিটার সহ সেট করা হয়। SwiftUI স্বয়ংক্রিয়ভাবে shadowPath প্রয়োগ করে এবং রেন্ডারিং কর্মক্ষমতা পরিচালনা করে। উন্নত ছায়ার জন্য (অভ্যন্তরীণ ছায়া, একাধিক ছায়া), LinearGradient সহ overlay() ব্যবহার করুন।
// SwiftUI: shadow মডিফায়ারের মাধ্যমে ছায়া
import SwiftUI
VStack {
Text("ছায়া সহ কার্ড")
.padding()
.background(Color.white)
.cornerRadius(16)
.shadow(
color: .black.opacity(0.15),
radius: 10,
x: 0,
y: 4
)
}
iOS-এ ছায়ার কর্মক্ষমতা: যদি shadowPath সেট না করা হয়, Core Animation প্রতিটি ফ্রেমে লেয়ারের আকৃতির উপর ভিত্তি করে ছায়া গণনা করে, যা অ্যানিমেশনের সময় পিছিয়ে পড়াcause করতে পারে। স্থির উপাদানের জন্য, সর্বদা shadowPath সেট করুন। অ্যানিমেটেড উপাদানের জন্য, একটি আলাদা লেয়ারে ছায়া ক্যাশ করতে CALayer-এ shouldRasterize = true ব্যবহার করুন। SwiftUI-এ, রাস্টারাইজেশন .drawingGroup()-এর মাধ্যমে পরিচালিত হয়।
Android-এ, Material Design-এ ছায়াগুলি elevation-এর মাধ্যমে বাস্তবায়িত হয় — একটি View বৈশিষ্ট্য যা z-স্থানাঙ্কে উপাদানের উচ্চতা সেট করে। সিস্টেম elevation এবং outlineProvider (উপাদানের রূপরেখা) এর উপর ভিত্তি করে স্বয়ংক্রিয়ভাবে ছায়া রেন্ডার করে। elevation যত বেশি, ছায়া তত বড় এবং ঝাপসা। যেসব View Material Design (যেমন AppCompat) থেকে উত্তরাধিকার সূত্রে পাওয়া যায় না, সেগুলির জন্য ছায়া কেবল হার্ডওয়্যার ত্বরণ সক্ষম থাকলেই কাজ করে।
<!-- XML: অ্যাট্রিবিউটের মাধ্যমে elevation -->
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="12dp"
app:cardElevation="6dp">
<!-- কার্ডের বিষয়বস্তু -->
</androidx.cardview.widget.CardView>
Android View System-এ কাস্টম ছায়ার জন্য, OutlineProvider ব্যবহার করুন। ViewOutlineProvider আপনাকে outline.setRoundRect() বা outline.setPath()-এর মাধ্যমে একটি নির্বিচারে আকৃতি সেট করতে দেয়। OutlineProvider ছাড়া, ছায়া View-এর আয়তাকার আকৃতির উপর ভিত্তি করে রেন্ডার করা হয়, যা কোণ গোলাকারকরণকে বিবেচনা করে না।
// Kotlin: ছায়ার জন্য কাস্টম OutlineProvider
import android.graphics.Outline
import android.view.View
import android.view.ViewOutlineProvider
val myView: View = findViewById(R.id.myView)
myView.outlineProvider = object : ViewOutlineProvider() {
override fun getOutline(view: View, outline: Outline) {
outline.setRoundRect(
0, 0, view.width, view.height,
12f // কোণের ব্যাসার্ধ
)
}
}
myView.elevation = 8f // px-এ ছায়ার উচ্চতা
myView.translationZ = 4f // চাপলে অতিরিক্ত উচ্চতা
Jetpack Compose-এ, ছায়াগুলি Modifier.shadow() এবং Card ও Surface কম্পোনেন্টে elevation-এর মাধ্যমে পরিচালিত হয়। Modifier.shadow() elevation এবং shape গ্রহণ করে। View System-এর বিপরীতে, Compose নিজস্ব রেন্ডার পাইপলাইনে ছায়া রেন্ডার করে, যা Android-এর সকল সংস্করণে আরও পূর্বানুমানযোগ্য আচরণ প্রদান করে।
// Jetpack Compose: Modifier.shadow-এর মাধ্যমে ছায়া
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
Card(
modifier = Modifier.shadow(
elevation = 6.dp,
shape = RoundedCornerShape(12.dp),
clip = false
),
colors = CardDefaults.cardColors(containerColor = Color.White)
) {
Text("কাস্টম ছায়া সহ Card")
}
ছায়ার সঠিক ব্যবহার ইন্টারফেসের ধারণা উন্নত করে, যখন ভুল ব্যবহার ভিজ্যুয়াল গোলমাল সৃষ্টি করে এবং কর্মক্ষমতা হ্রাস করে। Material Design পাঁচটি elevation স্তর নির্ধারণ করে: 0 dp (কোনো ছায়া নেই), 1–4 dp (বাটন, চিপস), 6–12 dp (কার্ড, মেনু), 16–24 dp (ডায়ালগ, বটম শিট), 24+ dp (মোডাল উইন্ডো, FAB)।
| স্তর | Elevation | উপাদান | ছায়ার বৈশিষ্ট্য |
|---|---|---|---|
| 0 | 0 dp | টেক্সট, আইকন, পটভূমি | কোনো ছায়া নেই, সমতল স্তর |
| 1 | 1–4 dp | বাটন, ইনপুট ফিল্ড | হালকা ছায়া, ছোট সরণ |
| 2 | 6–12 dp | কার্ড, Snackbar | মাঝারি ছায়া, লক্ষণীয় ঝাপসা |
| 3 | 16–24 dp | ডায়ালগ, মেনু | গভীর ছায়া, বড় ঝাপসা |
| 4 | 24+ dp | মোডাল উইন্ডো | সর্বোচ্চ ছায়া, উপাদান ভাসে |
সেরা অনুশীলন: (1) যেসব উপাদানের মনোযোগ আকর্ষণ করা উচিত নয় (পটভূমি, বিভাজক) সেগুলির জন্য ছায়া ব্যবহার করবেন না, (2) ছায়ার উচ্চতা উপাদানের গুরুত্বের সাথে মিলিত হওয়া উচিত — যত বেশি গুরুত্বপূর্ণ, তত বেশি উচ্চতা, (3) বাটন চাপার সময়, স্পর্শকাতর প্রতিক্রিয়ার জন্য অ্যানিমেশন সহ elevation কমিয়ে দিন, (4) গাঢ় পটভূমিতে ছায়া এড়িয়ে চলুন — ছায়ার পরিবর্তে overlay (হালকা/গাঢ়) ব্যবহার করুন। Material You (Android 12+)-এ, ছায়াগুলি থিমের সাথে খাপ খায়: গাঢ় পটভূমিতে, elevation একটি রঙের স্তর (surface tint) দ্বারা প্রতিস্থাপিত হয়।
Flutter-এ, ছায়াগুলি BoxDecoration-এর ভিতরে BoxShadow-এর মাধ্যমে বাস্তবায়িত হয়। BoxShadow color, offset, blurRadius এবং spreadRadius গ্রহণ করে। Flutter একাধিক ছায়া সমর্থন করে: BoxShadow-এর একটি তালিকা পাস করলে জটিল প্রভাব তৈরি করা যায় — উদাহরণস্বরূপ, বাইরের ছায়া + ভিতরের হাইলাইট। PhysicalModel একটি বিকল্প যা আকৃতির (BeveledRectangleBorder, CircleBorder) উপর ভিত্তি করে একটি ভৌত ছায়া অনুকরণ করে।
// Flutter: BoxDecoration + BoxShadow-এর মাধ্যমে ছায়া
import 'package:flutter/material.dart';
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12.0),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.15),
offset: Offset(0, 4),
blurRadius: 8.0,
spreadRadius: 0,
),
],
),
child: Text('ছায়া সহ কন্টেইনার'),
)
// ভৌত ছায়ার জন্য PhysicalModel
PhysicalModel(
color: Colors.white,
elevation: 6.0,
shadowColor: Colors.black.withOpacity(0.2),
borderRadius: BorderRadius.circular(12.0),
child: Text('ছায়া সহ ভৌত মডেল'),
)
কর্মক্ষমতা: একাধিক ছায়া সহ BoxShadow প্রতিটি পরিবর্তনে পুনরায় পেইন্ট করতে পারে। স্থির উপাদানের জন্য, PhysicalModel ব্যবহার করুন — এটি একটি পৃথক লেয়ারে (RepaintBoundary) ছায়া ক্যাশ করে। Flutter 3.16+-এ, অভিযোজিত ছায়া সহ Material 3 elevation সমর্থিত, যা থিম (হালকা/গাঢ়) অনুযায়ী রঙ এবং ঝাপসা পরিবর্তন করে।
সচরাচর জিজ্ঞাসিত প্রশ্ন
Elevation হল z-স্থানাঙ্কে একটি উপাদানের সংখ্যাগত উচ্চতা, যেখানে shadow (ছায়া) হল এই উচ্চতা দ্বারা সৃষ্ট ভিজ্যুয়াল ইফেক্ট। Android-এ, elevation একটি View বৈশিষ্ট্য যা স্বয়ংক্রিয়ভাবে ছায়া তৈরি করে। ডিজাইনে, elevation এবং shadow প্রায়শই পরস্পর পরিবর্তনযোগ্যভাবে ব্যবহৃত হয়, কিন্তু প্রযুক্তিগতভাবে elevation হল কারণ এবং shadow হল ফলাফল।
পরীক্ষা করুন: (1) View-এ elevation 0-এর বেশি সেট করা আছে, (2) outlineProvider সেট করা আছে (যদি View Material লাইব্রেরি থেকে না হয়), (3) হার্ডওয়্যার ত্বরণ সক্রিয় আছে (ম্যানিফেস্টে android:hardwareAccelerated="true")। CardView স্বয়ংক্রিয়ভাবে outlineProvider পরিচালনা করে। কাস্টম Views-এর জন্য, view.outlineProvider = ViewOutlineProvider.BACKGROUND কল করুন।
CALayer সরাসরি অভ্যন্তরীণ ছায়া সমর্থন করে না। একটি সংমিশ্রণ ব্যবহার করুন: মাস্কের ভিতরে কালো রঙ এবং স্বচ্ছতা সহ CAGradientLayer, অথবা একটি রাস্টার অভ্যন্তরীণ ছায়া সহ UIImageView ওভারলে করুন। SwiftUI-এ, অভ্যন্তরীণ ছায়া LinearGradient এবং blendMode(.multiply) সহ overlay-এর মাধ্যমে বাস্তবায়িত হয়।
Android-এ, অ্যানিমেশনের জন্য translationZ ব্যবহার করুন: স্থির অবস্থায় elevation = 2 dp, চাপলে translationZ = 4 dp (মোট উচ্চতা 6 dp)। iOS-এ, বাটন রূপান্তরের সাথে একই সাথে shadowOffset এবং shadowRadius অ্যানিমেট করুন। SwiftUI-এ, Modifier.shadow()-এর মাধ্যমে elevation পরিবর্তনের সাথে withAnimation ব্যবহার করুন। Flutter-এ, BoxShadow পরিবর্তনের সাথে AnimatedContainer ব্যবহার করুন।
Material Design একটি স্ক্রিনে তিনটি elevation স্তরের বেশি না ব্যবহার করার সুপারিশ করে। যদি ছায়া সহ আরও উপাদান থাকে, তবে সেগুলিকে একই উচ্চতার গ্রুপে একত্রিত করুন। অত্যধিক ছায়া ভিজ্যুয়াল গোলমাল সৃষ্টি করে এবং মিড-রেঞ্জ ও বাজেট ডিভাইসে রেন্ডারিং কর্মক্ষমতা হ্রাস করে।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন