add fonts ,also fix the sidebar and header

This commit is contained in:
Saeed AB 2025-09-18 15:44:03 +03:30
parent 58331eed7a
commit 2cf6071a38
37 changed files with 1910 additions and 59 deletions

View File

@ -1,7 +1,5 @@
@import "tailwindcss";
/* Persian/Farsi font support */
@import url("https://fonts.googleapis.com/css2?family=Vazirmatn:wght@100..900&display=swap");
@import url(/font/fontiran.css);
@theme {
--font-sans:
@ -49,6 +47,17 @@ body {
}
}
body {
font-family: IRANYekanX !important;
direction: rtl;
background-color: #cdcdcd;
margin: 0;
}
h1, h2, h3, h4, h5, h6,input, textarea {
font-family: IRANYekanX !important;
}
/* RTL Support */
html[dir="rtl"] {
direction: rtl;
@ -251,7 +260,7 @@ html[dir="rtl"] body {
/* Persian/Farsi font class */
.font-persian {
font-family: "Vazirmatn", "Inter", ui-sans-serif, system-ui, sans-serif;
font-family: IRANYekanX;
}
/* Custom utility classes */

View File

@ -179,7 +179,7 @@ export function LoginForm({ onSuccess }: LoginFormProps) {
<div className="flex justify-end">
<CheckboxField
id="remember"
label="همیشه متصل بمانم"
label="همیشه متصل بمان"
checked={formData.rememberMe}
onChange={(checked) => updateField("rememberMe", checked)}
disabled={isLoading}

View File

@ -1,4 +1,4 @@
import { useEffect, useState } from "react";
import React, { useEffect, useState } from "react";
import { useAuth } from "~/contexts/auth-context";
import { Link } from "react-router";
import { cn } from "~/lib/utils";
@ -12,6 +12,7 @@ import {
Menu,
ChevronDown,
Server,
ChevronLeft ,
} from "lucide-react";
import apiService from "~/lib/api";
@ -20,12 +21,14 @@ interface HeaderProps {
onToggleSidebar?: () => void;
className?: string;
title?: string;
titleIcon?: React.ComponentType<{ className?: string }> | null;
}
export function Header({
onToggleSidebar,
className,
title = "صفحه اول",
titleIcon,
}: HeaderProps) {
const { user } = useAuth();
const [isProfileMenuOpen, setIsProfileMenuOpen] = useState(false);
@ -65,7 +68,24 @@ export function Header({
{/* Page Title */}
<h1 className="text-xl flex items-center justify-center gap-4 font-bold text-white font-persian">
<PanelLeft /> {title}
{/* Right-side icon for current page */}
{titleIcon ? (
<div className="flex items-center gap-2 mr-4">
{React.createElement(titleIcon, { className: "w-5 h-5 " })}
</div>
) : (
<PanelLeft />
)}
{title.includes("-") ? (
<span className="flex items-center gap-1">
{title.split("-")[0]}
<ChevronLeft className="inline-block w-4 h-4" />
{title.split("-")[1]}
</span>
) : (
title
)}
</h1>
</div>
@ -89,9 +109,7 @@ export function Header({
onClick={() => setIsProfileMenuOpen(!isProfileMenuOpen)}
className="flex items-center gap-2 text-gray-300"
>
<div className="w-8 h-8 bg-gradient-to-r from-emerald-500/20 to-teal-500/20 text-emerald-400 rounded-full flex items-center justify-center">
<User className="h-4 w-4" />
</div>
<div className="hidden sm:block text-right">
<div className="text-sm font-medium font-persian">
{user?.name} {user?.family}
@ -100,7 +118,9 @@ export function Header({
{user?.username}
</div>
</div>
<ChevronDown className="h-3 w-3" />
<div className="w-8 h-8 bg-gradient-to-r from-emerald-500/20 to-teal-500/20 text-emerald-400 rounded-lg flex items-center justify-center">
<User className="h-4 w-4" />
</div>
</Button>
</div>
{/* Profile Dropdown */}

View File

@ -19,6 +19,8 @@ export function DashboardLayout({
const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false);
const [isMobileSidebarOpen, setIsMobileSidebarOpen] = useState(false);
const [isStrategicAlignmentPopupOpen, setIsStrategicAlignmentPopupOpen] = useState(false);
const [currentTitle, setCurrentTitle] = useState<string | undefined>(title ?? "صفحه اول");
const [currentTitleIcon, setCurrentTitleIcon] = useState<React.ComponentType<{ className?: string }> | null | undefined>(undefined);
const toggleSidebarCollapse = () => {
setIsSidebarCollapsed(!isSidebarCollapsed);
@ -61,6 +63,10 @@ export function DashboardLayout({
onToggleCollapse={toggleSidebarCollapse}
className="h-full flex-shrink-0 relative z-10"
onStrategicAlignmentClick={() => setIsStrategicAlignmentPopupOpen(true)}
onTitleChange={(info) => {
setCurrentTitle(info.title);
setCurrentTitleIcon(info.icon ?? null);
}}
/>
</div>
@ -71,7 +77,8 @@ export function DashboardLayout({
<Header
onToggleSidebar={toggleMobileSidebar}
className="flex-shrink-0"
title={title}
title={currentTitle}
titleIcon={currentTitleIcon}
/>
{/* Main content */}

View File

@ -813,7 +813,7 @@ export function GreenInnovationPage() {
<div className="params flex flex-col gap-3.5">
{Object.entries(recycleParams).map((el, index) => {
return (
<div className="param flex flex-row justify-between items-center">
<div key={index} className="param flex flex-row justify-between items-center">
<div className="flex flex-row gap-2">
{el[1].icon}
<span className="font-normal text-sm font-persian">

View File

@ -587,10 +587,10 @@ export function ProcessInnovationPage() {
return (
<DashboardLayout title="نوآوری در فرآیند">
<div className="p-6 space-y-4">
<div className="p-6 py-2 space-y-4">
{/* Stats Cards */}
<div className="flex gap-6">
<div className="space-y-6 w-full">
<div className="space-y-4 w-full">
{/* Stats Grid */}
<div className="grid grid-cols-2 gap-3">
{loading || statsLoading

View File

@ -15,7 +15,6 @@ import {
UsersIcon,
Wrench,
} from "lucide-react";
import moment from "moment-jalaali";
import { useCallback, useEffect, useRef, useState } from "react";
import toast from "react-hot-toast";
import { Badge } from "~/components/ui/badge";
@ -56,7 +55,6 @@ import { DashboardLayout } from "../layout";
import { Skeleton } from "~/components/ui/skeleton";
import { Tooltip as TooltipSh, TooltipTrigger, TooltipContent } from "~/components/ui/tooltip";
moment.loadPersian({ usePersianDigits: true });
interface ProjectData {
project_no: string;

View File

@ -15,18 +15,28 @@ import {
Settings,
Star,
Workflow,
DiscAlbum
DiscAlbum,
House,
ListTodo,
LightbulbIcon,
Radar
} from "lucide-react";
import React, { useState } from "react";
import { Link, useLocation } from "react-router";
import { useAuth } from "~/contexts/auth-context";
import { cn } from "~/lib/utils";
interface TitleInfo {
title: string;
icon?: React.ComponentType<{ className?: string }> | null;
}
interface SidebarProps {
isCollapsed?: boolean;
onToggleCollapse?: () => void;
className?: string;
onStrategicAlignmentClick?: () => void;
onTitleChange?: (info: TitleInfo) => void;
}
interface MenuItem {
@ -43,48 +53,48 @@ const menuItems: MenuItem[] = [
{
id: "dashboard",
label: "صفحه اصلی",
icon: LayoutDashboard,
icon: House,
href: "/dashboard",
},
{
id: "project-management",
label: "مدیریت اجرای پروژه‌ها",
icon: FolderKanban,
icon: ListTodo,
href: "/dashboard/project-management",
},
{
id: "innovation-basket",
label: "سبد فناوری و نوآوری",
icon: Box,
icon: LightbulbIcon,
children: [
{
id: "product-innovation",
label: "نوآوری در محصول",
icon: Package,
icon: null,
href: "/dashboard/innovation-basket/product-innovation",
},
{
id: "process-innovation",
label: "نوآوری در فرآیند",
icon: Workflow,
icon: null,
href: "/dashboard/innovation-basket/process-innovation",
},
{
id: "digital-innovation",
label: "نوآوری دیجیتال",
icon: MonitorSmartphone,
icon: null,
href: "/dashboard/innovation-basket/digital-innovation",
},
{
id: "green-innovation",
label: "نوآوری سبز",
icon: Leaf,
icon: null,
href: "/dashboard/innovation-basket/green-innovation",
},
{
id: "internal-innovation",
label: "نوآوری ساخت داخل",
icon: Building2,
icon: null,
href: "/dashboard/innovation-basket/internal-innovation",
},
],
@ -92,13 +102,13 @@ const menuItems: MenuItem[] = [
{
id: "ecosystem",
label: "زیست بوم فناوری و نوآوری",
icon: Globe,
icon: Radar,
href: "/dashboard/ecosystem",
},
{
id: "ideas",
label: "ایده‌های فناوری و نوآوری",
icon: Lightbulb,
icon: House,
href: "/dashboard/manage-ideas-tech",
},
{
@ -136,6 +146,7 @@ export function Sidebar({
onToggleCollapse,
className,
onStrategicAlignmentClick,
onTitleChange,
}: SidebarProps) {
const location = useLocation();
const [expandedItems, setExpandedItems] = useState<string[]>([]);
@ -158,6 +169,29 @@ export function Sidebar({
});
setExpandedItems(newExpandedItems);
// Update header title based on current route
// If a child route is active, use that child's label prefixed by parent label
let activeTitle: string | undefined = undefined;
let activeIcon: React.ComponentType<{ className?: string }> | null | undefined = undefined;
menuItems.forEach((item) => {
if (item.children) {
const activeChild = item.children.find(
(child) => child.href && location.pathname === child.href
);
if (activeChild) {
activeTitle = `${item.label}-${activeChild.label}`;
// prefer child icon for the page; fallback to parent
activeIcon = activeChild.icon ?? item.icon ?? null;
}
}
if (!activeTitle && item.href && location.pathname === item.href) {
activeTitle = item.label;
activeIcon = item.icon ?? null;
}
});
if (onTitleChange) {
onTitleChange({ title: activeTitle ?? "صفحه اول", icon: activeIcon ?? null });
}
};
autoExpandParents();
@ -207,8 +241,13 @@ export function Sidebar({
const ItemIcon = item.icon;
const handleClick = () => {
// Only update header title for navigable items (those with href)
if (item.href && item.href !== "#") {
const icon = item.icon ?? null;
onTitleChange?.({ title: item.label, icon });
}
if (item.id === "strategic-alignment") {
console.log("test")
onStrategicAlignmentClick?.();
} else if (item.id === "logout") {
logout();
@ -222,7 +261,7 @@ export function Sidebar({
<button
key={item.id}
className={cn(
"flex items-center justify-center w-full px-2 rounded-lg mt-4 transition-all duration-200 group",
"flex items-center justify-center w-full px-2 rounded-none mt-4 transition-all duration-200 group",
)}
onClick={handleClick}
>
@ -242,22 +281,24 @@ export function Sidebar({
<Link to={item.href} className="block">
<div
className={cn(
"flex items-center justify-between w-full py-2 px-3 rounded-lg transition-all duration-200 group",
"flex items-center justify-between rounded-none w-full py-2 px-3 transition-all duration-200 group",
level === 0 ? "mb-1" : "mb-0.5 mr-4",
isActive
? " text-emerald-400 border-r-2 border-emerald-400"
: "text-gray-300 hover:bg-gradient-to-r hover:from-emerald-500/10 hover:to-teal-500/10 hover:text-emerald-300",
? " text-pr-green border-r-2 border-pr-green"
: "text-gray-300 hover:text-pr-green",
isCollapsed && level === 0 && "justify-center px-2",
item.id === "logout" && "hover:bg-red-500/10 hover:text-red-400"
item.id === "logout" && "hover:text-pr-red"
)}
>
<div className="flex items-center gap-3 min-w-0 flex-1">
<ItemIcon
className={cn(
"w-5 h-5 flex-shrink-0",
isActive ? "text-emerald-400" : "text-current"
)}
/>
{ItemIcon && (
<ItemIcon
className={cn(
"w-5 h-5 flex-shrink-0",
isActive ? "text-pr-green" : "text-current"
)}
/>
)}
{!isCollapsed && (
<span className="font-persian text-sm font-medium truncate">
{item.label}
@ -268,7 +309,7 @@ export function Sidebar({
{!isCollapsed && (
<div className="flex items-center gap-2 flex-shrink-0">
{item.badge && (
<span className="bg-gradient-to-r from-emerald-500/20 to-teal-500/20 text-emerald-400 text-xs font-medium px-1.5 py-0.5 rounded-full min-w-[20px] text-center font-persian">
<span className="bg-gradient-to-r from-emerald-500/20 to-teal-500/20 text-pr-green text-xs font-medium px-1.5 py-0.5 rounded-full min-w-[20px] text-center font-persian">
{item.badge}
</span>
)}
@ -299,22 +340,24 @@ export function Sidebar({
>
<div
className={cn(
"flex items-center justify-between w-full py-2 px-3 rounded-lg transition-all duration-200 group",
"flex items-center justify-between w-full py-2 px-3 rounded-none transition-all duration-200 group",
level === 0 ? "mb-1" : "mb-0.5 mr-4",
isActive
? " text-emerald-400 border-r-2 border-emerald-400"
: "text-gray-300 hover:bg-gradient-to-r hover:from-emerald-500/10 hover:to-teal-500/10 hover:text-emerald-300",
? " text-pr-green border-r-2 border-pr-green"
: "text-gray-300 cursor-pointer hover:text-pr-green",
isCollapsed && level === 0 && "justify-center px-2",
item.id === "logout" && "hover:bg-red-500/10 hover:text-red-400"
item.id === "logout" && "hover:text-pr-red"
)}
>
<div className="flex items-center gap-3 min-w-0 flex-1">
<ItemIcon
className={cn(
"w-5 h-5 flex-shrink-0",
isActive ? "text-emerald-400" : "text-current"
)}
/>
{ItemIcon && (
<ItemIcon
className={cn(
"w-5 h-5 flex-shrink-0",
isActive ? "text-pr-green" : "text-current"
)}
/>
)}
{!isCollapsed && (
<span className="font-persian text-sm font-medium truncate">
{item.label}
@ -325,7 +368,7 @@ export function Sidebar({
{!isCollapsed && (
<div className="flex items-center gap-2 flex-shrink-0">
{item.badge && (
<span className="bg-gradient-to-r from-emerald-500/20 to-teal-500/10 text-emerald-400 text-xs font-medium px-1.5 py-0.5 rounded-full min-w-[20px] text-center font-persian">
<span className="bg-gradient-to-r from-emerald-500/20 to-teal-500/10 text-pr-green text-xs font-medium px-1.5 py-0.5 rounded-full min-w-[20px] text-center font-persian">
{item.badge}
</span>
)}
@ -340,7 +383,7 @@ export function Sidebar({
(child) =>
child.href && location.pathname === child.href
)
? "text-emerald-400"
? "text-pr-green"
: "text-current"
)}
/>
@ -392,7 +435,7 @@ export function Sidebar({
/>
<div className="font-persian">
<div className="text-sm font-semibold text-white">
داشبورد اینوژن
اینوژن بندر امام
</div>
<div className="text-xs text-gray-400">نسخه ۰.۱</div>
</div>
@ -431,7 +474,7 @@ export function Sidebar({
</div>
{/* Collapse Toggle */}
{onToggleCollapse && (
{/* {onToggleCollapse && (
<div className="p-3 border-t border-gray-500/30">
<button
onClick={onToggleCollapse}
@ -448,7 +491,7 @@ export function Sidebar({
)}
</button>
</div>
)}
)} */}
</div>
);
}

File diff suppressed because one or more lines are too long

426
public/font/IranYekanX.html Normal file
View File

@ -0,0 +1,426 @@
<!doctype html>
<html lang="fa">
<head>
<meta charset="utf-8">
<title>IRANYekanX Family Type face: خانواده فونت ایران‌سنس</title>
<meta name="fontiran.com:license" content="کد ۵ رقمی لایسنس">
<link href="style.css" rel="stylesheet">
</head>
<body dir="rtl">
<div class="wrapper">
<div class="mainbox">
<div class="titelbox">
<h1>بِسْمِ اللهِ الرَّحْمَنِ الرَّحِيمِ</h1>
</div>
<div class="alphabet" style="line-height:200px" > د </div>
<div class="rightbox">
<br>
<span class="text-xlarge">ن وَالْقَلَمِ وَ مَا يَسْطُرُون</span>
<br>
<span class="text-xlarge"> نون؛ سوگند به قلم و آنچه می نويسند. </span>
<br>
<span class="text-large"> Noon. I swear by the pen and what the angels write </span>
<br>
<br>
</div>
</div>
<div class="mainbox">
<div class="titelbox" style="letter-spacing: 0px">
<h1>نکاتی درباره تایپوگرافی وب</h1>
</div>
<div class="alphabet" style="line-height:250px" > ج </div>
<div class="rightbox">
<p>از زمان پیدایش نخستین وب سایت، متن ها یکی از اجزای مهم صفحات وب بودند. هر چند به مرور زمان با ورود تصاویر، صوت و فیلم کمی از بار مسئولیت متون کم شد اما هنوز جایگاه خود را از دست نداده اند و بخش مهمی از کار را به عهده دارند.</p>
<p>بسیاری از طراحان وب سایت به صورت تجربی بهترین ترکیب و ظاهر را برای نمایش متن ها انتخاب می کنند. اما اصولی وجود دارد که با رعایت آن ها، تاثیرپذیری و زیبایی سایت چند برابر خواهد شد.</p>
<p>در ادامه مطلب قصد داریم تعدادی از اصول مقدماتی تایپوگرافی را به اختصار مرور کنیم. هرچند بسیاری از دوستان با این نکات آشنا هستند؛ اما شاید مرور آن ها خالی از لطف نباشد.</p>
</div>
</div>
<div class="mainbox">
<div class="titelbox" style="letter-spacing: 0px">
<h1>تاثیر اندازه فونت و سلسله مراتب تگ‌ها</h1>
</div>
<div class="alphabet" style="line-height:170px"> ن </div>
<div class="rightbox">
<p>فونت های داخل سایت باید به گونه ای قرار گیرند که کاربر به راحتی بتواند آن ها را بخواند. نوع فونت، وزن و کوچک (یا بزرگ) بودن اندازه آن ممکن است تمایل کاربر برای بازگشت به وب سایت را کاهش دهد. قواعد و قوانین زیادی برای انتخاب بهترین فونت وجود دارد.</p>
<p>در زیر می توانید ۱۲ وزن مختلف <strong>خانواده فونت ایران‌سنس</strong> را در شرایط یکسان مشاهده کنید. لازم به ذکر است برای این صفحه از وزن معمولی (Normal) استفاده شده است.</p>
</div>
</div>
<div class="mainbox">
<div class="mainbox2">
<div class="text-thin" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (Thin)</div>
<div class="text-UltraLight" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (UltraLight)</div>
<div class="text-light" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (Light)</div>
<div class="text-regular" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (Regular)</div>
<div class="text-medium" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (Medium)</div>
<div class="text-demibold" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (demiBold)</div>
<div class="text-bold" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (Bold)</div>
<div class="text-extrabold" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (ExtraBold)</div>
<div class="text-black" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (Black)</div>
<div class="text-extrablack" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (ExtraBlack)</div>
<div class="text-heavy" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (Heavy)</div>
</div>
</div>
<div class="mainboxnegativ">
<div class="mainbox2">
<div class="text-thin" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (Thin)</div>
<div class="text-UltraLight" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (UltraLight)</div>
<div class="text-light" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (Light)</div>
<div class="text-regular" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (Regular)</div>
<div class="text-medium" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (Medium)</div>
<div class="text-demibold" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (demiBold)</div>
<div class="text-bold" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (Bold)</div>
<div class="text-extrabold" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (ExtraBold)</div>
<div class="text-black" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (Black)</div>
<div class="text-extrablack" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (ExtraBlack)</div>
<div class="text-heavy" style="font-size:2.2em">من نه آنم که زبونی کشم از چرخ فلک (Heavy)</div>
</div>
</div>
<div class="mainbox">
<div class="titelbox" style="letter-spacing: 0px">
<h1>تگ‌های هدینگ</h1>
</div>
<div class="alphabet" style="line-height:180px"> و </div>
<div class="rightbox">
<p>در این بین، استفاده از تگ های هدینگ مناسب و رعایت سلسله مراتب آن ها، هم مفهوم نوشته را بهتر منتقل می کند و هم تاثیر قابل توجهی در نتایج موتورهای جستجو خواهد داشت. این نکته یکی از فاکتورهای مهم در بهینه سازی وب سایت برای موتورهای جستجو (Search Engine Optimization) است.</p>
<p>نمونه ای از خروجی تگ های هدینگ با سایز استاندارد مربوطه به فونت های فونت ایران‌سنس را در زیر مشاهده می کنید.</p>
</div>
</div>
<div class="mainbox">
<div class="mainbox2">
<h1>(H1) نابرده رنج گنج میسر نمی شود. No gain without pain </h1>
<h2>(H2) نابرده رنج گنج میسر نمی شود. No gain without pain</h2>
<h3>(H3) نابرده رنج گنج میسر نمی شود. No gain without pain</h3>
<h4>(H4) نابرده رنج گنج میسر نمی شود. No gain without pain </h4>
<h5>(H5) نابرده رنج گنج میسر نمی شود. No gain without pain</h5>
<h6>(H6) نابرده رنج گنج میسر نمی شود. No gain without pain</h6>
</div>
</div>
<div class="mainboxnegativ">
<div class="mainbox2">
<h1>(H1) نابرده رنج گنج میسر نمی شود. No gain without pain </h1>
<h2>(H2) نابرده رنج گنج میسر نمی شود. No gain without pain</h2>
<h3>(H3) نابرده رنج گنج میسر نمی شود. No gain without pain</h3>
<h4>(H4) نابرده رنج گنج میسر نمی شود. No gain without pain </h4>
<h5>(H5) نابرده رنج گنج میسر نمی شود. No gain without pain</h5>
<h6>(H6) نابرده رنج گنج میسر نمی شود. No gain without pain</h6>
</div>
</div>
<div class="mainbox">
<div class="titelbox" style="letter-spacing: 0px">
<h1>سطر و ستون بندی</h1>
</div>
<div class="alphabet" style="line-height:200px"> م </div>
<div class="rightbox">
<p>معمولاً هرگاه مقدار نوشته از یک سطر بیشتر شود ناگزیر به ستون بندی هستیم. و این کار ما را با چند متغییر مواجه خواهد کرد:</p>
<p>۱- <strong>عرض ستون‌های متنی</strong> که حاوی حداقل۷ کلمه باشد بهترین انتخاب است. اگر ستون کوتاه‌تر باشد چشم بیننده در اثر حرکت‌های زود به زود از پایان یک سطر به ابتدای سطر بعدی خسته خواهد شد. علاوه بر این لبه ستون‌هایی با عرض کم نیز همیشه دندانه ای و بی نظم خواهد بود. ستون‌هایی با عرض طولانی هم برای خواننده آزار دهنده است چرا که چشم در حرکت بازگشت از انتهای یک سطر به ابتدای سطر بعدی ممکن است دچار اشتباه شود.
<p>۲- <strong>لدینگ یا همان فاصله سطر </strong> هم در ستون بندی اهمیت دارد. ستون‌های فشرده اگرچه به لحاظ گرافیکی منسجم و زیبا هستند اما عمل خواندن را مختل می کنند و در مقابل، فاصله سطر زیاد نیز باعث نازیبایی و خستگی چشم خواننده می‌شود. فاصله سطر همیشه می تواند با توجه به نوع فونت و عرض ستون‌ها تغییر کند. بدین ترتیب که فونت‌هایی با دندانه‌های بلند‌تر و ستون‌هایی با عرض بیشتر به لدینگ بیشتری نیاز دارند.
<p>۳- <strong>همترازی </strong> هم یکی از متغییرهای پر بحث در ستون بندی است. اما به طور کوتاه و خلاصه باید گفت که بهتر است در متن فارسی از همترازی یا همان Justification استفاده نکنید. این عمل اگرچه لبه پاراگراف شما را مرتب خواهد کرد اما تنظیمات فاصله حروف را تغییر خواهد داد و در نتیجه باعث کاهش خوانایی خواهد شد. </div>
</div>
<div class="mainbox">
<div class="mainbox2negativ">(IRANYekanX Thin)</div>
<div class="farsiparagraph"><span class="text-thin">ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-thin">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainbox">
<div class="mainbox2negativ">(IRANYekanX UltraLight)</div>
<div class="farsiparagraph"><span class="text-UltraLight">
ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-UltraLight">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainbox">
<div class="mainbox2negativ">(IRANYekanX Light)</div>
<div class="farsiparagraph"><span class="text-light">
ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-light">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainbox">
<div class="mainbox2negativ">(IRANYekanX Regular)</div>
<div class="farsiparagraph"><span class="text-regular">
ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-regular">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainbox">
<div class="mainbox2negativ">(IRANYekanX Mediume)</div>
<div class="farsiparagraph"><span class="text-medium">
ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-medium">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainbox">
<div class="mainbox2negativ">(IRANYekanX DemiBold)</div>
<div class="farsiparagraph"><span class="text-demibold">
ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-demibold">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainbox">
<div class="mainbox2negativ">(IRANYekanX Bold)</div>
<div class="farsiparagraph"><span class="text-bold">
ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-bold">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainbox">
<div class="mainbox2negativ">(IRANYekanX ExtraBold)</div>
<div class="farsiparagraph"><span class="text-extrabold">
ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-extrabold">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainbox">
<div class="mainbox2negativ">(IRANYekanX Black)</div>
<div class="farsiparagraph"><span class="text-black">
ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-black">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainbox">
<div class="mainbox2negativ">(IRANYekanX ExtraBlack)</div>
<div class="farsiparagraph"><span class="text-extrablack">
ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-extrablack">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainbox">
<div class="mainbox2negativ">(IRANYekanX Heavy)</div>
<div class="farsiparagraph"><span class="text-heavy">
ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-heavy">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainboxnegativ">
<div class="mainbox2negativ">(IRANYekanX Thin)</div>
<div class="farsiparagraph"><span class="text-thin">
ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-thin">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainboxnegativ">
<div class="mainbox2negativ">(IRANYekanX UltraLight)</div>
<div class="farsiparagraph"><span class="text-UltraLight">
ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-UltraLight">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainboxnegativ">
<div class="mainbox2negativ">(IRANYekanX Light)</div>
<div class="farsiparagraph"><span class="text-light">
ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-light">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainboxnegativ">
<div class="mainbox2negativ">(IRANYekanX Regular)</div>
<div class="farsiparagraph"><span class="text-regular">
ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-regular">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainboxnegativ">
<div class="mainbox2negativ">(IRANYekanX Mediume)</div>
<div class="farsiparagraph"><span class="text-medium">
ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-medium">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainboxnegativ">
<div class="mainbox2negativ">(IRANYekanX DemiBold)</div>
<div class="farsiparagraph"><span class="text-demibold">
ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-demibold">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainboxnegativ">
<div class="mainbox2negativ">(IRANYekanX Bold)</div>
<div class="farsiparagraph"><span class="text-bold">
ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-bold">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainboxnegativ">
<div class="mainbox2negativ">(IRANYekanX ExtraBold)</div>
<div class="farsiparagraph"><span class="text-extrabold">
ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-extrabold">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainboxnegativ">
<div class="mainbox2negativ">(IRANYekanX Black)</div>
<div class="farsiparagraph"><span class="text-black">
ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-black">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainboxnegativ">
<div class="mainbox2negativ">(IRANYekanX ExtraBlack)</div>
<div class="farsiparagraph"><span class="text-extrablack">
ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-extrablack">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainboxnegativ">
<div class="mainbox2negativ">(IRANYekanX Heavy)</div>
<div class="farsiparagraph"><span class="text-heavy">
ایران‌یکان IRANYekanX از ترکیب دو فونت پر طرفدار یکان و ایران‌سنس پدید آمده است. بخشی از منحنی‌های ایران‌سنس به ساختار عمودی و افقی یکان اضافه شده است تا ایران‌یکان IRANYekanX فونتی باشد که با وجود هندسی بودن خشک و مکانیکی نباشد. این فونت با سبک‌های طراحی کمینه‌گرا Minimal سازگاری خوبی دارد و همنشین مناسبی برای فونت‌های سن‌سریف لاتین است. </span></div>
<div class="englishparagraph"><span class="text-heavy">
Roboto has a dual nature. It has a mechanical skeleton and the forms are largely geometric. At the same time, the font features friendly and open curves. While some grotesks distort their letterforms to force a rigid rhythm, Roboto doesnt compromise, allowing letters to be settled into their natural width. This makes for a more natural reading rhythm more commonly found in humanist and serif types.</span></div>
</div>
<div class="mainbox">
<div class="titelbox" style="letter-spacing: 0px">
<h1>اعداد و علائم در فونت فارسی</h1>
</div>
<div class="alphabet" style="line-height:470px"> ظ </div>
<div class="rightbox">
<p><span class="text-xlarge">اعداد فارسی: <strong>۱۲۳۴۵۶۷۸۹۰</strong></span><br>
<span class="text-xlarge">اعداد عربی: <strong>۱۲۳٤٥٦۷۸۹۰</strong></span><br>
<span class="text-xlarge">اعداد انگلیسی: <strong>1234567890</strong></span></p>
<p>برای تایپ اعداد فارسی در محیط وب از <a href="http://fontiran.com/%d9%86%d8%b5%d8%a8-%da%a9%db%8c%d8%a8%d9%88%d8%b1%d8%af-%d9%81%d8%a7%d8%b1%d8%b3%db%8c-%d8%a7%d8%b3%d8%aa%d8%a7%d9%86%d8%af%d8%a7%d8%b1%d8%af-%d8%af%d8%b1-%d9%88%db%8c%d9%86%d8%af%d9%88%d8%b28-%d9%88/">کیبورد استاندارد فارسی</a> استفاده کنید. در ویندوز ۸ و یا بالاتر این کیبورد، با نام Persian(Standard)Keyboard در لیست کیبوردهای ویندوز وجود دارد. همچنین می توانید از <a href="http://persian-computing.ir/download/Iranian_Standard_Persian_Keyboard_(ISIRI_9147)_(Version_2.0).zip">این آدرس</a> آن را دانلود و نصب کنید.</p>
<span>
<p>با استفاده از کیبورد استاندارد می‌توانید ممیز فارسی را تایپ کنید.<br>
<span>میانبر این علامت کلیدهای <span class="text-medium">Shift+3</span> است. به این شکل: <strong class="text-xlarge">۳٫۱۴</strong></span><br>
<span >ممیز فارسی با علامت اسلش تفاوت دارد :<strong class="text-xlarge">۳/۱۴</strong></span>
</p>
<p>با استفاده از کیبورد استاندارد می‌توانید جداکننده هزارگان فارسی را تایپ کنید.<br>
<span>میانبر این علامت کلیدهای <strong>Shift+2</strong> است. به این شکل: <strong class="text-xlarge">۹٬۲۱۰٬۰۰۰</strong></span><br>
<span >این علامت با جدا کننده هزارگان انگلیسی تفاوت دارد : <strong class="text-xlarge">۹,۲۱۰,۰۰۰</strong></span>
</p>
</div>
</div>
<div class="mainbox">
<div class="titelbox" style="letter-spacing: 0px">
<h1> نسبت‌های طلایی</h1>
</div>
<div class="alphabet2">
<div style="padding-left:20px">
۳٫۷۷۷ &divide; ۱٫۶۱۸ = <span class="text-regular text-underline">۲٫۳۳۵</span>
<br>
۶٫۱۱۲ &divide; ۱٫۶۱۸ = <span class="text-regular text-underline">۳٫۷۷۷</span>
<br>
۹٫۸۸۹ &divide; ۱٫۶۱۸ = <span class="text-regular text-underline">۶٫۱۱۲</span>
<br>
۱۶ &divide; ۱٫۶۱۸ = <span class="text-regular text-underline">۹٫۸۸۹</span>
<br>
.......................................
<br>
۱۶ &times; ۱٫۶۱۸ = <span class="text-regular text-underline">۲۵٫۸۸۸</span>
<br>
۲۵٫۸۸۸ &times; ۱٫۶۱۸ = <span class="text-regular text-underline">۴۱٫۸۸۷</span>
<br>
۴۱٫۸۸۷ &times; ۱٫۶۱۸ = <span class="text-regular text-underline">۶۷٫۷۷۳</span>
<br>
۶۷٫۷۷۳ &times; ۱٫۶۱۸ = <span class="text-regular text-underline">۱۰۹٫۶۵۶</span>
</div>
</div>
<div class="rightbox">
<p>اهمیت اندازه فونت در خوانایی و زیبا شدن صفحه وب سایت بر کسی پوشیده نیست. در کنار این بحث، موارد دیگری مانند ارتفاع خطوط، فاصله ها، ابعاد قسمت های مختلف و ... نیز در بحث تایپوگرافی اهمیت زیادی دارند.</p>
<p>برای محاسبه این اعداد می توانیم از سری اعداد متناسب (Modular Scale) استفاده کنیم. در حقیقت از تعدادی عدد پشت سر هم که بر اساس مضرب خاصی تشکیل شده اند برای تنظیمات ارتفاع خط، فاصله ها، ابعاد و ... استفاده می کنیم. نسبت (عدد) طلایی همان مضرب اعداد است.</p>
<p>به عنوان مثال می خواهیم از سایز 16px <strong>فونت ایران‌سنس</strong> به عنوان فونت و سایز اصلی متن صفحات استفاده کنیم. عدد فی (phi) یونانی که معادل ۱٫۶۱۸۰۳۳۹۸۸۷ (به اختصار ۱٫۶۱۸) است را به عنوان نسبت طلایی در نظر می گیریم. بنابراین سری اعدادی به شکل روبرو خواهیم داشت:</p>
<p>
به کمک این اعداد و استفاده از آن ها در صفحات وب سایت خود می توانیم خوانایی و زیبایی آن را افزایش دهیم. علاوه بر آن، اگر از واحدهای نسبی مانند em استفاده شود، امکانات بیشتری در اختیار طراح و بازدیدکننده خواهد بود. البته <strong>سری اعداد بر مبنای نسبت طلایی</strong> فقط در تایپوگرافی وب سایت کاربرد ندارد.
این اعداد می تواند ادامه داشته باشد (<span class="text-regular text-underline">۱٬۲۱۵٫۹۸۱</span> ، <span class="text-regular text-underline">۱٬۹۶۷٫۴۵۷</span> ، <span class="text-regular text-underline">۳٬۱۸۳٫۳۴۵</span> و ...).
</p>
</div>
</div>
<div class="mainbox">
<div class="rightbox">
<br>
در این فایل سعی کردیم همراه با یک مطلب آموزشی کوتاه، نحوه استفاده از خانواده فونت ایران‌سنس و پیش نمایشی از قسمت های مختلف آن را مرور کنیم.
<br>
برای مشاهده راهنمای نحوه قراردادن فونت ها در وب سایت خود، به <a href="http://fontiran.com/%d9%86%d8%b5%d8%a8-%d9%81%d9%88%d9%86%d8%aa-%d8%a7%db%8c%d8%b1%d8%a7%d9%86-%d8%b3%d9%86%d8%b3-iransans-%d8%b1%d9%88%db%8c-%d9%88%d8%a8%d8%b3%d8%a7%db%8c%d8%aa/" target="_blank">این آدرس</a> مراجعه کنید.
<br>
<br>
<br>
<br>
<br>
</div>
<div class="alphabet" style="line-height:180px">ء</div>
</div>
<br>
<div class="footer">
Copyright (c) 2021 by <a href="http://fontiran.com">www.fontiran.com</a> (Moslem Ebrahimi). All rights reserved.
<br>
To use this font, it is necessary to obtain the license from www.fontiran.com
</div>
</div>
</body>
</html>

108
public/font/fontiran.css Normal file
View File

@ -0,0 +1,108 @@
/**
*
* Name: IRANYekanX Fonts
* Version: 2.4
* Author: Moslem Ebrahimi (moslemebrahimi.com)
* Created on: Aug 02, 2022
* Updated on: Aug 02, 2022
* Website: http://fontiran.com
* Copyright: Commercial/Proprietary Software
--------------------------------------------------------------------------------------
فونت ایران یکان X یک نرم افزار مالکیتی محسوب می شود. جهت آگاهی از قوانین استفاده از این فونت ها لطفا به وب سایت (فونت ایران دات کام) مراجعه نمایید
--------------------------------------------------------------------------------------
IRANYekanX fonts are considered a proprietary software. To gain information about the laws regarding the use of these fonts, please visit www.fontiran.com
--------------------------------------------------------------------------------------
This set of fonts are used in this project under the license: (.....)
------------------------------------------------------------------------------------- fonts/-
*
**/
@font-face {
font-family: IRANYekanX;
font-style: normal;
font-weight: 100;
src: url('woff/IRANYekanX-Thin.woff') format('woff'),
url('woff2/IRANYekanX-Thin.woff2') format('woff2');
}
@font-face {
font-family: IRANYekanX;
font-style: normal;
font-weight: 200;
src: url('woff/IRANYekanX-UltraLight.woff') format('woff'),
url('woff2/IRANYekanX-UltraLight.woff2') format('woff2');
}
@font-face {
font-family: IRANYekanX;
font-style: normal;
font-weight: 300;
src: url('woff/IRANYekanX-Light.woff') format('woff'),
url('woff2/IRANYekanX-Light.woff2') format('woff2');
}
@font-face {
font-family: IRANYekanX;
font-style: normal;
font-weight: 500;
src: url('woff/IRANYekanX-Medium.woff') format('woff'),
url('woff2/IRANYekanX-Medium.woff2') format('woff2');
}
@font-face {
font-family: IRANYekanX;
font-style: normal;
font-weight: 600;
src: url('woff/IRANYekanX-DemiBold.woff') format('woff'),
url('woff2/IRANYekanX-DemiBold.woff2') format('woff2');
}
@font-face {
font-family: IRANYekanX;
font-style: normal;
font-weight: 800;
src: url('woff/IRANYekanX-ExtraBold.woff') format('woff'),
url('woff2/IRANYekanX-ExtraBold.woff2') format('woff2');
}
@font-face {
font-family: IRANYekanX;
font-style: normal;
font-weight: 900;
src: url('woff/IRANYekanX-Black.woff') format('woff'),
url('woff2/IRANYekanX-Black.woff2') format('woff2');
}
@font-face {
font-family: IRANYekanX;
font-style: normal;
font-weight: 950;
src: url('woff/IRANYekanX-ExtraBlack.woff') format('woff'),
url('woff2/IRANYekanX-ExtraBlack.woff2') format('woff2');
}
@font-face {
font-family: IRANYekanX;
font-style: normal;
font-weight: 1000;
src: url('woff/IRANYekanX-Heavy.woff') format('woff'),
url('woff2/IRANYekanX-Heavy.woff2') format('woff2');
}
@font-face {
font-family: IRANYekanX;
font-style: normal;
font-weight: bold;
src: url('woff/IRANYekanX-Bold.woff') format('woff'),
url('woff2/IRANYekanX-Bold.woff2') format('woff2');
}
@font-face {
font-family: IRANYekanX;
font-style: normal;
font-weight: normal;
src: url('woff/IRANYekanX-Regular.woff') format('woff'),
url('woff2/IRANYekanX-Regular.woff2') format('woff2');
}

463
public/font/fonttest.html Normal file
View File

@ -0,0 +1,463 @@
<head>
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=9" />
<title>IRANYekanX</title>
<style type="text/css" media="screen">
@font-face { font-family: 'WOFF IRANYekanX-Thin'; src: url('woff/IRANYekanX-Thin.woff'); }
@font-face { font-family: 'WOFF IRANYekanX-UltraLight'; src: url('woff/IRANYekanX-UltraLight.woff'); }
@font-face { font-family: 'WOFF IRANYekanX-Light'; src: url('woff/IRANYekanX-Light.woff'); }
@font-face { font-family: 'WOFF IRANYekanX-Regular'; src: url('woff/IRANYekanX-Regular.woff'); }
@font-face { font-family: 'WOFF IRANYekanX-Medium'; src: url('woff/IRANYekanX-Medium.woff'); }
@font-face { font-family: 'WOFF IRANYekanX-DemiBold'; src: url('woff/IRANYekanX-DemiBold.woff'); }
@font-face { font-family: 'WOFF IRANYekanX-Bold'; src: url('woff/IRANYekanX-Bold.woff'); }
@font-face { font-family: 'WOFF IRANYekanX-ExtraBold'; src: url('woff/IRANYekanX-ExtraBold.woff'); }
@font-face { font-family: 'WOFF IRANYekanX-Black'; src: url('woff/IRANYekanX-Black.woff'); }
@font-face { font-family: 'WOFF IRANYekanX-ExtraBlack'; src: url('woff/IRANYekanX-ExtraBlack.woff'); }
@font-face { font-family: 'WOFF IRANYekanX-Heavy'; src: url('woff/IRANYekanX-Heavy.woff'); }
@font-face { font-family: 'WOFF2 IRANYekanX-Thin'; src: url('woff2/IRANYekanX-Thin.woff2'); }
@font-face { font-family: 'WOFF2 IRANYekanX-UltraLight'; src: url('woff2/IRANYekanX-UltraLight.woff2'); }
@font-face { font-family: 'WOFF2 IRANYekanX-Light'; src: url('woff2/IRANYekanX-Light.woff2'); }
@font-face { font-family: 'WOFF2 IRANYekanX-Regular'; src: url('woff2/IRANYekanX-Regular.woff2'); }
@font-face { font-family: 'WOFF2 IRANYekanX-Medium'; src: url('woff2/IRANYekanX-Medium.woff2'); }
@font-face { font-family: 'WOFF2 IRANYekanX-DemiBold'; src: url('woff2/IRANYekanX-DemiBold.woff2'); }
@font-face { font-family: 'WOFF2 IRANYekanX-Bold'; src: url('woff2/IRANYekanX-Bold.woff2'); }
@font-face { font-family: 'WOFF2 IRANYekanX-ExtraBold'; src: url('woff2/IRANYekanX-ExtraBold.woff2'); }
@font-face { font-family: 'WOFF2 IRANYekanX-Black'; src: url('woff2/IRANYekanX-Black.woff2'); }
@font-face { font-family: 'WOFF2 IRANYekanX-ExtraBlack'; src: url('woff2/IRANYekanX-ExtraBlack.woff2'); }
@font-face { font-family: 'WOFF2 IRANYekanX-Heavy'; src: url('woff2/IRANYekanX-Heavy.woff2'); }
body {
background: white;
color: black;
}
.features, .label, a, #controls {
font: normal normal normal small sans-serif;
}
.features .emojiButton {
vertical-align: -5%;
font-size: small;
}
.emojiButton {
cursor: pointer;
}
#flexbox {
display: flex;
flex-flow: column;
height: 100%;
}
#controls {
flex: 0 1 auto;
margin: 0;
padding: 0;
width: 100%;
border: 0px solid transparent;
height: auto;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
}
#metricsLine {
background-color: #EEE;
border-top: 1px solid #AAA;
border-bottom: 1px solid #AAA;
width: 100%;
margin: 0.2em 0;
padding: 0 0;
font-size: 2em;
white-space: nowrap;
overflow-x: auto;
overflow-y: hidden;
text-overflow: none;
display: none;
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* Internet Explorer 10+ */
}
#metricsLine::-webkit-scrollbar { /* WebKit */
width: 0;
height: 0;
}
#waterfall {
flex: 1 1 auto;
border: 0 solid transparent;
margin: 0;
padding: 0;
width: 100%;
color: black;
overflow-x: hidden;
overflow-y: scroll;
font-family: "WOFF IRANYekanX-Thin";
font-feature-settings: "kern" on, "liga" on, "calt" on;
-moz-font-feature-settings: "kern" on, "liga" on, "calt" on;
-webkit-font-feature-settings: "kern" on, "liga" on, "calt" on;
-ms-font-feature-settings: "kern" on, "liga" on, "calt" on;
-o-font-feature-settings: "kern" on, "liga" on, "calt" on;
}
div, p {
padding: 0;
margin: 0;
}
#waterfall p {
margin-bottom: 0.8em;
overflow-wrap: break-word;
}
.○ .sampletext {
-webkit-text-stroke: 1px black;
-webkit-text-fill-color: #FFF0;
}
.features, .label, a {
color: #888;
}
.label {
background-color: #ddd;
padding: 2px 3px;
}
span#p08 { font-size: 08pt; padding: 08pt 0; }
span#p09 { font-size: 09pt; padding: 09pt 0; }
span#p10 { font-size: 10pt; padding: 10pt 0; }
span#p11 { font-size: 11pt; padding: 11pt 0; }
span#p12 { font-size: 12pt; padding: 12pt 0; }
span#p13 { font-size: 13pt; padding: 13pt 0; }
span#p14 { font-size: 14pt; padding: 14pt 0; }
span#p15 { font-size: 15pt; padding: 15pt 0; }
span#p16 { font-size: 16pt; padding: 16pt 0; }
span#largeParagraph { font-size: 32pt; padding: 32pt 0; }
span#veryLargeParagraph { font-size: 100pt; padding: 100pt 0; }
.otFeatureLabel {
color: #666;
background-color: #ddd;
padding: 0.2em 0.5em 0.3em 0.5em;
margin: 0 .04em;
line-height: 2em;
border-radius: 0.3em;
border: 0;
text-align:center;
}
.otFeatureLabel, .otFeature {
position: relative;
opacity: 1;
pointer-events: auto;
white-space: nowrap;
}
.otFeatureLabel {
padding: 0.2em 0.5em 0.3em 0.5em;
margin: 0 .04em;
line-height: 2em;
color: #666;
background-color: #ddd;
border-radius: 0.3em;
border: 0;
text-align: center;
z-index: 6;
}
.wrapper {
width: auto;
overflow: hidden;
border: 0 solid transparent;
}
select {
float: left;
margin: 0 0.5em 0 0;
padding: 0;
}
input[type=text] {
border: 1px solid #999;
margin: 0;
width: 100%;
}
.features {
clear: left;
}
input[type=checkbox]:checked + label {
visibility: visible;
color: #fff;
background-color: #888;
}
.otFeature {
visibility: collapse;
margin: 0 -1em 0 0;
}
.otFeatureLabel .tooltip {
visibility: hidden;
background-color: #333;
color: white;
text-align: center;
padding: 0px 5px;
top: -2em;
left: 0;
position: absolute;
z-index: 8;
}
.otFeatureLabel:hover .tooltip {
visibility: visible;
}
#featureLine {
display: none;
border-bottom: 1px solid #999;
padding: 0.5em 0;
margin-bottom: 0.5em;
}
/* Footer paragraph: */
#helptext {
color: black;
background-color: #ddd;
position: fixed;
bottom: 0;
padding: 2px
width: 100%;
font: x-small sans-serif;
}
/* Dark Mode */
@media (prefers-color-scheme: dark) {
body {
background: #333;
}
.features, .label, a, body, p, #metricsLine {
color: white;
}
.label {
background-color: black;
padding: 2px 3px;
}
.otFeatureLabel, input[type=text] {
color: white;
background-color: black;
}
input[type=checkbox]:checked + label {
color: black;
background-color: #aaa;
}
#helptext {
background-color: #777;
}
.○ .sampletext {
-webkit-text-stroke: 1px white;
-webkit-text-fill-color: #0000;
}
#metricsLine {
background-color: #222;
border-color: #777;
}
}
</style>
</head>
<body onload="document.getElementById('textInput').focus();setCharset();">
<div id="flexbox">
<div id="controls">
<div>
<select size="1" id="fontFamilySelector" name="fontFamilySelector" onchange="changeFont()">
<option value="IRANYekanX-Thin.woff">WOFF IRANYekanX-Thin</option>
<option value="IRANYekanX-UltraLight.woff">WOFF IRANYekanX-UltraLight</option>
<option value="IRANYekanX-Light.woff">WOFF IRANYekanX-Light</option>
<option value="IRANYekanX-Regular.woff">WOFF IRANYekanX-Regular</option>
<option value="IRANYekanX-Medium.woff">WOFF IRANYekanX-Medium</option>
<option value="IRANYekanX-DemiBold.woff">WOFF IRANYekanX-DemiBold</option>
<option value="IRANYekanX-Bold.woff">WOFF IRANYekanX-Bold</option>
<option value="IRANYekanX-ExtraBold.woff">WOFF IRANYekanX-ExtraBold</option>
<option value="IRANYekanX-Black.woff">WOFF IRANYekanX-Black</option>
<option value="IRANYekanX-ExtraBlack.woff">WOFF IRANYekanX-ExtraBlack</option>
<option value="IRANYekanX-Heavy.woff">WOFF IRANYekanX-Heavy</option>
<option value="IRANYekanX-Thin.woff2">WOFF2 IRANYekanX-Thin</option>
<option value="IRANYekanX-UltraLight.woff2">WOFF2 IRANYekanX-UltraLight</option>
<option value="IRANYekanX-Light.woff2">WOFF2 IRANYekanX-Light</option>
<option value="IRANYekanX-Regular.woff2">WOFF2 IRANYekanX-Regular</option>
<option value="IRANYekanX-Medium.woff2">WOFF2 IRANYekanX-Medium</option>
<option value="IRANYekanX-DemiBold.woff2">WOFF2 IRANYekanX-DemiBold</option>
<option value="IRANYekanX-Bold.woff2">WOFF2 IRANYekanX-Bold</option>
<option value="IRANYekanX-ExtraBold.woff2">WOFF2 IRANYekanX-ExtraBold</option>
<option value="IRANYekanX-Black.woff2">WOFF2 IRANYekanX-Black</option>
<option value="IRANYekanX-ExtraBlack.woff2">WOFF2 IRANYekanX-ExtraBlack</option>
<option value="IRANYekanX-Heavy.woff2">WOFF2 IRANYekanX-Heavy</option>
</select>
<div class="wrapper" spellcheck="false">
<input type="text" value="Type Text Here." id="textInput" onclick="this.select();" onkeyup="updateParagraph()" />
</div>
</div>
<p class="features">
<a href="javascript:setCharset();">Charset</a>
<a href="javascript:setLat1();">Lat1</a>
&ensp;
<a href="https://caniuse.com/#feat=woff">woff</a>
<a href="https://caniuse.com/#feat=woff2">woff2</a>
&ensp;
<a onclick="toggleInverse();" id="invert" class="emojiButton">🔲</a>
<label><input type="checkbox" id="kern" value="kern" class="otFeature" onchange="updateFeatures()" checked><label for="kern" class="otFeatureLabel">kern</label>
<label><input type="checkbox" id="liga" value="liga" class="otFeature" onchange="updateFeatures()" checked><label for="liga" class="otFeatureLabel">liga/clig</label>
<label><input type="checkbox" id="calt" value="calt" class="otFeature" onchange="updateFeatures()" checked><label for="calt" class="otFeatureLabel">calt</label>
<input type="checkbox" id="numr" value="numr" class="otFeature" onchange="updateFeatures()"><label for="numr" class="otFeatureLabel">numr</label>
<input type="checkbox" id="dnom" value="dnom" class="otFeature" onchange="updateFeatures()"><label for="dnom" class="otFeatureLabel">dnom</label>
<input type="checkbox" id="frac" value="frac" class="otFeature" onchange="updateFeatures()"><label for="frac" class="otFeatureLabel">frac</label>
<input type="checkbox" id="init" value="init" class="otFeature" onchange="updateFeatures()"><label for="init" class="otFeatureLabel">init</label>
<input type="checkbox" id="medi" value="medi" class="otFeature" onchange="updateFeatures()"><label for="medi" class="otFeatureLabel">medi</label>
<input type="checkbox" id="fina" value="fina" class="otFeature" onchange="updateFeatures()"><label for="fina" class="otFeatureLabel">fina</label>
<input type="checkbox" id="rlig" value="rlig" class="otFeature" onchange="updateFeatures()"><label for="rlig" class="otFeatureLabel">rlig</label>
<input type="checkbox" id="dlig" value="dlig" class="otFeature" onchange="updateFeatures()"><label for="dlig" class="otFeatureLabel">dlig</label>
<input type="checkbox" id="salt" value="salt" class="otFeature" onchange="updateFeatures()"><label for="salt" class="otFeatureLabel">salt</label>
<input type="checkbox" id="ss01" value="ss01" class="otFeature" onchange="updateFeatures()"><label for="ss01" class="otFeatureLabel">ss01</label>
<input type="checkbox" id="ss02" value="ss02" class="otFeature" onchange="updateFeatures()"><label for="ss02" class="otFeatureLabel">ss02</label>
<input type="checkbox" id="ss03" value="ss03" class="otFeature" onchange="updateFeatures()"><label for="ss03" class="otFeatureLabel">ss03</label>
<input type="checkbox" id="ss04" value="ss04" class="otFeature" onchange="updateFeatures()"><label for="ss04" class="otFeatureLabel">ss04</label>
<label><input type="checkbox" value="show" onchange="updateFeatures();document.getElementById('featureLine').style.display=this.checked?'block':'none'">CSS</label>
<label><input type="checkbox" value="show" onchange="updateFeatures();document.getElementById('metricsLine').style.display=this.checked?'block':'none'">Metrics</label>
</p>
<p class="features" id="featureLine">font-feature-settings: "kern" on, "liga" on, "calt" on;</p>
</div>
<div id="waterfall" class="●">
<div id="metricsLine"></div>
<p><span class="label">08</span>&nbsp;<span class="sampletext" id="p08"></span></p>
<p><span class="label">09</span>&nbsp;<span class="sampletext" id="p09"></span></p>
<p><span class="label">10</span>&nbsp;<span class="sampletext" id="p10"></span></p>
<p><span class="label">11</span>&nbsp;<span class="sampletext" id="p11"></span></p>
<p><span class="label">12</span>&nbsp;<span class="sampletext" id="p12"></span></p>
<p><span class="label">13</span>&nbsp;<span class="sampletext" id="p13"></span></p>
<p><span class="label">14</span>&nbsp;<span class="sampletext" id="p14"></span></p>
<p><span class="label">15</span>&nbsp;<span class="sampletext" id="p15"></span></p>
<p><span class="label">16</span>&nbsp;<span class="sampletext" id="p16"></span></p>
<p><span class="sampletext" id="largeParagraph"></span></p>
<p><span class="sampletext" id="veryLargeParagraph"></span></p>
</div>
</div>
<!-- Disclaimer -->
<p id="helptext" onmouseleave="vanish(this);">
Ctrl-R: Reset Charset. Ctrl-L: Latin1. Ctrl-J: LTR/RTL. Ctrl-comma/period: step through fonts. Pull mouse across this note to make it disappear.
</p>
<script type="text/javascript">
const selector = document.getElementById("fontFamilySelector");
const selectorOptions = selector.options;
const selectorLength = selectorOptions.length;
document.addEventListener('keyup', keyAnalysis);
function keyAnalysis(event) {
if (event.ctrlKey) {
if (event.code == 'KeyR') {
setCharset();
} else if (event.code == 'KeyL') {
setLat1();
} else if (event.code == 'KeyJ') {
toggleLeftRight();
} else if (event.code == 'Period') {
selector.selectedIndex = (selector.selectedIndex + 1) % selectorLength;
changeFont();
} else if (event.code == 'Comma') {
var newIndex = selector.selectedIndex - 1;
if (newIndex<0) {
newIndex = selectorLength - 1;
}
selector.selectedIndex = newIndex;
changeFont();
}
}
}
function updateParagraph() {
// update paragraph text based on user input:
const txt = document.getElementById('textInput');
const paragraphs = document.getElementsByClassName('sampletext');
for (i = 0; i < paragraphs.length; i++) {
paragraph = paragraphs[i];
paragraph.textContent = txt.value;
}
// update other elements:
document.getElementById('metricsLine').textContent = txt.value;
}
function updateFeatures() {
// update features based on user input:
// first, get feature on/off line:
var cssCode = "";
var codeLine = "";
var checkboxes = document.getElementsByClassName("otFeature")
for (i = 0; i < checkboxes.length; i++) {
var checkbox = checkboxes[i];
codeLine += '"'+checkbox.id+'" ';
codeLine += checkbox.checked ? 'on, ' : 'off, ';
if (checkbox.name=="kern") {
cssCode += "font-kerning: "
cssCode += checkbox.checked ? 'normal; ' : 'none; ';
} else if (checkbox.name=="liga") {
codeLine += '"clig" '
codeLine += checkbox.checked ? 'on, ' : 'off, ';
cssCode += "font-variant-ligatures: "
cssCode += checkbox.checked ? 'common-ligatures contextual; ' : 'no-common-ligatures no-contextual; ';
} else if (checkbox.name=="dlig") {
cssCode += "font-variant-ligatures: "
cssCode += checkbox.checked ? 'discretionary-ligatures; ' : 'no-discretionary-ligatures; ';
} else if (checkbox.name=="hlig") {
cssCode += "font-variant-ligatures: "
cssCode += checkbox.checked ? 'historical-ligatures; ' : 'no-historical-ligatures; ';
}
}
codeLine = codeLine.slice(0, -2)
// then, apply line for every browser:
const prefixes = ["","-moz-","-webkit-","-ms-","-o-",];
const suffix = "font-feature-settings: "
for (i = 0; i < prefixes.length; i++) {
var prefix = prefixes[i];
cssCode += prefix
cssCode += suffix
cssCode += codeLine
cssCode += "; "
}
document.getElementById('waterfall').style.cssText = cssCode;
document.getElementById('featureLine').innerHTML = cssCode.replace(/;/g,";<br/>");
changeFont();
}
function changeFont() {
var selected_index = selector.selectedIndex;
var selected_option_text = selector.options[selected_index].text;
document.getElementById('waterfall').style.fontFamily = selected_option_text;
}
function setDefaultText(defaultText) {
document.getElementById('textInput').value = decodeEntities(defaultText);
updateParagraph();
}
function setLat1() {
const lat1 = "من نه آنم که زبونی کشم از چرخ فلک";
return setDefaultText(lat1);
}
function setCharset() {
const completeCharSet =
'من نه آنم که زبونی کشم از چرخ فلک'
setDefaultText(completeCharSet);
}
function decodeEntities(string){
var elem = document.createElement('div');
elem.innerHTML = string;
return elem.textContent;
}
function vanish(item) {
item.style.setProperty("display", "none");
}
function toggleLeftRight() {
const waterfall = document.getElementById("waterfall");
if (waterfall.dir != "rtl") {
waterfall.dir = "rtl";
waterfall.align = "right";
} else {
waterfall.dir = "";
waterfall.align = "";
}
}
function toggleInverse() {
const testText = document.getElementById("waterfall");
if (testText) {
const link = document.getElementById("invert");
if (testText.className == "●") {
testText.className = "○";
link.textContent = "🔳";
} else {
testText.className = "●";
link.textContent = "🔲";
}
}
}
</script>
</body>

Binary file not shown.

243
public/font/style.css Normal file
View File

@ -0,0 +1,243 @@
@import url(fontiran.css); /* لینک فایلی که وظیفه بارگذاری فونت ها را برعهده دارد */
body {
font-family: IRANYekanX !important;
direction: rtl;
background-color: #cdcdcd;
margin: 0;
}
h1, h2, h3, h4, h5, h6,input, textarea {
font-family: IRANYekanX !important;
}
h1 {
font-weight: bold;
}
.wrapper {
max-width: 900px;
margin: 0 auto;
}
.ltr {
direction: ltr;
}
.text-right {
text-align: right;
}
.text-center {
text-align: center;
}
.text-left {
text-align: left;
}
.text-small {
font-size: 0.8em;
}
.text-xsmall {
font-size: 0.6em;
}
.text-large {
font-size: 1.2em;
}
.text-xlarge {
font-size: 1.4em;
}
.text-underline {
text-decoration:underline;
}
.text-thin {
font-weight: 100;
}
.text-UltraLight {
font-weight: 200;
}
.text-light {
font-weight: 300;
}
.text-regular {
font-weight: normal;
}
.text-medium {
font-weight: 500;
}
.text-demibold {
font-weight: 600;
}
.text-bold {
font-weight: bold;
}
.text-extrabold {
font-weight: 800;
}
.text-black {
font-weight: 900;
}
.text-extrablack {
font-weight: 950;
}
.text-heavy {
font-weight: 1000;
}
blockquote {
font-weight: 700;
padding: 10px;
border: 1px dashed #666666;
}
.mainbox {
width: 100%;
background-color: #EFEFEF;
display: table;
margin-bottom: 30px;
border-right: 8px solid #00adb5;
}
.mainboxnegativ {
width: 100%;
background-color: #303841;
display: table;
margin-bottom: 30px;
border-right: 8px solid #00adb5;
color: #F9F9F9;
}
.mainbox2 {
font-size: 1em;
width: 90%;
padding-right: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
.mainboxitalic {
font-size: 1em;
font-style: italic;
width: 90%;
padding-right: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
.mainbox3 {
width: 100%;
background-color: #DFDFDF;
display: table;
margin-bottom: 30px;
border-right: 8px solid #FF5EAA;
}
.mainbox2negativ {
font-size: 1em;
color: #F9F9F9;
background-color: #000000;
padding-right: 20px;
}
.farsiparagraph {
font-size: 1em;
width: 47%;
float:right;
padding-right: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
.farsiparagraph_negativ {
font-size: 1em;
color: #F9F9F9;
background-color: #000000;
width: 47%;
float:right;
padding-right: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
.englishparagraph {
font-size: 1em;
width: 47%;
float: left;
direction:ltr;
padding-left: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
.englishparagraph_negativ {
font-size: 1em;
color: #F9F9F9;
background-color: #000000;
width: 47%;
float: left;
direction:ltr;
padding-left: 20px;
padding-top: 10px;
padding-bottom: 10px;
}
.rightbox {
width: 60%;
padding-right: 20px;
padding-left: 5px;
float: right;
margin-left: 10px;
margin-bottom: 0px;
min-width: 0px;
background-color: #F7F7F7;
}
.titelbox {
width: 60%;
padding-right: 25px;
padding-left: 0px;
float: right;
margin-left: 10px;
margin-bottom: 0px;
min-width: 0px;
background-color: #d5d5d5;
color: #4B4B4B;
}
.lefttbox {
padding-right: 20px;
padding-left: 4px;
float: right;
margin-bottom: 10px;
min-width: 0px;
}
.alphabet {
width: 35%;
float: left;
font-size: 20em;
text-align: center;
font-weight: 700;
color: #999999;
}
.alphabet2 {
width: 35%;
float: left;
direction: ltr;
font-size: 1.6em;
text-align: left;
font-weight: 600;
color: #333333;
margin-top: 100px;
}
.footer {
font-weight: 400;
font-size: 0.7em;
text-align: center;
direction: ltr;
margin-bottom: 0px;
padding-bottom: 0px;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,7 +1,5 @@
import type { Config } from "@react-router/dev/config";
export default {
// Config options...
// Server-side render by default, to enable SPA mode set this to `false`
ssr: true,
ssr: false,
} satisfies Config;