अंडरलाइन, ओवरलाइन, और स्ट्राइकथ्रू को स्टाइल करने के लिए, नेटिव text-decoration प्रॉपर्टी का इस्तेमाल करें. इसके लिए, बॉर्डर, बैकग्राउंड ग्रेडिएंट या सूडो-एलिमेंट का इस्तेमाल न करें. नेटिव डेकोरेशन, रैप की गई लाइनों में टेक्स्ट को फ़ॉलो करता है, फ़ॉन्ट की मेट्रिक को ट्रैक करता है, ग्लिफ़ डिसेंडर को स्किप करता है, और नेस्ट किए गए एलिमेंट से इनहेरिट करता है. इसलिए, इनमें से किसी को भी फिर से लागू करने की ज़रूरत नहीं होती. इस गाइड के आखिर में दी गई बॉक्स-आधारित तकनीकों का इस्तेमाल सिर्फ़ तब करें, जब सजावट को टेक्स्ट के साथ चलाने के बजाय, उसकी आउटलाइन बनानी हो या उसे रैप करना हो.
टेक्स्ट डेकोरेशन, सिर्फ़ लिंक पर ही नहीं, बल्कि किसी भी टेक्स्ट पर लागू होते हैं. अगर अंडरलाइन किया गया टेक्स्ट कोई लिंक नहीं है, तो पक्का करें कि उसे लिंक न समझा जाए. किसी लिंक को डेकोरेट करते समय, डेस्टिनेशन पर ले जाने वाले असली <a href> का इस्तेमाल करें. साथ ही, स्क्रिप्ट हैंडलर वाले href="javascript:void(0)" का इस्तेमाल न करें. नया टैब खोलने के लिए, target="_blank" rel="noopener" जोड़ें. असली लिंक में मिडल-क्लिक, कॉपी-लिंक, और स्क्रीन रीडर की सुविधा काम करती है.
लाइन को स्टाइल करना
text-decoration शॉर्टहैंड की मदद से लाइन, स्टाइल, रंग, और मोटाई सेट करें. साथ ही, text-underline-offset की मदद से टेक्स्ट के बीच का गैप सेट करें. सिलेक्टर को :where() में रैप करें, ताकि डिफ़ॉल्ट वैल्यू की कोई खास जानकारी न हो और बाद में किया गया कोई भी बदलाव, कस्टम प्रॉपर्टी की ज़रूरत के बिना लागू हो जाए.
:where(.decorated) {
/* Thickness is relative to the font size (0.08em is an example value), so the line is not too heavy
on small text or too light on large text, and max() keeps it at least 1px so it never disappears. */
text-decoration: underline solid currentColor max(1px, 0.08em);
/* Use em so the gap scales with the font size. 0.2em clears most descenders; example value. */
text-underline-offset: 0.2em;
}
/* Example hover state: a softer line that firms up on hover and focus. The 50% mix and
0.12em thickness are example values. */
:where(.decorated) {
text-decoration-color: color-mix(in srgb, currentColor, transparent);
}
:where(.decorated:is(:hover, :focus-visible)) {
text-decoration-color: currentColor;
text-decoration-thickness: max(1px, 0.12em);
}
/* Other lines are a different text-decoration-line on the same properties */
.decorated-over { text-decoration-line: overline; }
.decorated-through { text-decoration-line: line-through; }
text-decoration-style में solid, double, dotted, dashed, और wavy से पेमेंट किया जा सकता है. text-underline-offset सिर्फ़ अंडरलाइन पर लागू होता है.
डिज़ाइन के लिए शुरुआती पॉइंट:
- मोटाई: मुख्य टेक्स्ट के लिए, करीब
0.06emसे0.1em. हेडिंग और हाइलाइट की गई स्थितियों के लिए, ज़्यादा मोटाई (0.1emसे0.15em) का इस्तेमाल करें. - ऑफ़सेट: करीब
0.15emसे0.25em. बिंदु वाली और लहरदार लाइनों को सॉलिड लाइनों की तुलना में थोड़ी ज़्यादा जगह की ज़रूरत होती है. इसलिए, उनके लिए ऑफ़सेट बढ़ाएं. - रंग:
currentColorसे लाइन का रंग, टेक्स्ट के रंग से मैच करता है. टेक्स्ट के रंग का हल्का मिक्स, जो कर्सर घुमाने पर गहरा हो जाता है. इससे लिंक की लंबी लाइनें साफ़ तौर पर दिखती हैं. - स्टाइल: लिंक के लिए
solid, शब्दों और उनके छोटे रूपों के लिएdotted, और गड़बड़ियों जैसे एनोटेशन के लिएwavy.
यह कंट्रोल करना कि लाइन को कहां स्किप किया जाए
इंक स्किप करना
डिफ़ॉल्ट रूप से, अंडरलाइन और ओवरलाइन, ग्लिफ़ के उन हिस्सों के आस-पास टूट जाती हैं जो उन्हें क्रॉस करते हैं. जैसे, डिसेंडर. text-decoration-skip-ink को सेट करके, यह तय करें कि:
.decorated {
/* auto: skip ink for most scripts (default). none: draw straight through.
all: also skip ink in scripts where auto does not, such as Japanese or Chinese. */
text-decoration-skip-ink: all;
}
- लैटिन टेक्स्ट के लिए
autoका इस्तेमाल करें और इसे डिक्लेयर न करें: यह डिफ़ॉल्ट रूप से सेट होता है. allका इस्तेमाल तब करें, जब अंडरलाइन, बेसलाइन के काफ़ी करीब हो और आइडियोग्राफ़िक ग्लिफ़ को क्रॉस कर रही हो. इसके अलावा, इसका इस्तेमाल तब भी किया जा सकता है, जब अलग-अलग स्क्रिप्ट वाले टेक्स्ट को एक जैसा दिखाना हो.- बहुत मोटी लाइन या जान-बूझकर सजावटी लाइन के लिए,
noneका इस्तेमाल करें. इसमें गैप, ब्रेक की तरह दिखेंगे.
स्पेस को स्किप करना
text-decoration-skip-spaces से यह तय होता है कि स्पेस के नीचे लाइन खींची जाए या नहीं. डिफ़ॉल्ट रूप से, start end की वैल्यू, शुरुआत और आखिर के स्पेस को बिना सजाए छोड़ देती है.
.decorated {
/* Spaces collapse by default, so there is nothing to skip. Preserve them when the
leading or trailing spaces are meaningful, such as padded input values. */
white-space: pre;
/* none: decorate every space. all: skip every space, so each word is underlined separately.
start | end | start end: skip only leading, trailing, or both. */
text-decoration-skip-spaces: all;
}
text-decoration-skip-spaces का एलान तब तक न करें, जब तक कि डेकोरेशन को पैडिंग (none) को साफ़ तौर पर कवर न करना हो या हर शब्द (all) के बीच ब्रेक न करना हो. सामान्य इनलाइन टेक्स्ट, जैसे कि किसी लिंक के टेक्स्ट में कोई लीडिंग या ट्रेलिंग स्पेस नहीं होता है. इसलिए, एलान से कुछ नहीं होता.
लाइन को छोटा या बड़ा करना
text-decoration-inset, लाइन की शुरुआत और आखिर को मूव करता है. पॉज़िटिव वैल्यू से एंड अंदर की ओर खिंचता है और नेगेटिव वैल्यू से बाहर की ओर धकेला जाता है. एक वैल्यू से दोनों छोरों को मूव किया जा सकता है. दो वैल्यू से, शुरुआत और खत्म होने की वैल्यू को अलग-अलग सेट किया जा सकता है. प्रतिशत, सजाए गए बॉक्स के इनलाइन साइज़ को दिखाते हैं.
/* Small insets soften the ends of the line; larger ones read as a deliberately short line.
Both values are examples. */
.trimmed { text-decoration-inset: var(--deco-inset, 0.1em); }
.extended { text-decoration-inset: calc(var(--deco-inset, 0.1em) * -1); }
बिना बॉर्डर या बैकग्राउंड ग्रेडिएंट के, कर्सर घुमाने पर अंडरलाइन दिखाने के लिए, एंड को 100% तक ट्रिम करें और उसे वापस 0 पर ट्रांज़िशन करें:
.reveal {
text-decoration: underline; /* Always visible, including for reduced motion */
}
/* Only hide and animate the line when the user has not asked for reduced motion. */
@media (prefers-reduced-motion: no-preference) {
.reveal {
/* Trim the end by the full inline size so the line starts with zero length. */
text-decoration-inset: 0 100%;
/* 150ms to 300ms feels responsive without lagging; ease-out starts quickly. Example values. */
transition: text-decoration-inset var(--reveal-duration, 0.25s) ease-out;
}
/* Include :focus-visible so keyboard users get the same reveal as pointer users. */
.reveal:is(:hover, :focus-visible) {
text-decoration-inset: 0 0;
}
}
स्यूडो-एलिमेंट की मदद से कस्टम लाइन बनाना
जब लाइन का आकार ऐसा हो जिसे text-decoration ड्रॉ नहीं कर सकता, तब सूडो-एलिमेंट का इस्तेमाल करें. जैसे, टेढ़ी-मेढ़ी लाइन. इसके बाद, क्लिपिंग करके उसे दिखाएं. इसके लिए, किसी अतिरिक्त मार्कअप की ज़रूरत नहीं होती. इसलिए, लिंक एक सामान्य <a> रहता है.
<a class="draw" href="#">Hover to draw underline</a>
.draw {
position: relative;
display: inline-block;
color: inherit;
text-decoration: none;
padding-block-end: 0.4em; /* Space for the line below the text; example value */
}
.draw::after {
content: "";
position: absolute;
inset: auto 0 0 0;
block-size: 0.4em; /* Height of the squiggle; example value */
pointer-events: none;
border: var(--deco-thickness, max(1px, 0.08em)) solid var(--deco-color, currentColor);
/* A single shape strokes along its path, using the border width as the stroke. Example squiggle. */
border-shape: shape(from 0% 50%,
curve to 20% 50% with 5% 0% / 15% 100%,
smooth to 40% 50% with 35% 100%,
smooth to 60% 50% with 55% 100%,
smooth to 80% 50% with 75% 100%,
smooth to 100% 50% with 95% 100%);
}
/* Only hide and animate the line when the user has not asked for reduced motion;
otherwise it stays fully drawn. */
@media (prefers-reduced-motion: no-preference) {
.draw::after {
/* Clip the line away from the right edge. The negative block insets keep the stroke
from being cut off vertically. */
clip-path: inset(-1em 100% -1em 0);
/* A slightly slower draw than a hover reveal reads as drawing; example duration. */
transition: clip-path var(--draw-duration, 0.6s) ease-out;
}
.draw:is(:hover, :focus-visible)::after {
clip-path: inset(-1em 0 -1em 0); /* Fully drawn */
}
}
इसके बजाय, टेक्स्ट को बॉक्स से आउटलाइन करें
बॉक्स की दो प्रॉपर्टी, टेक्स्ट को सजाने के लिए उसके साथ लाइन चलाने के बजाय, उसकी आउटलाइन बनाती हैं. टेक्स्ट को पैडिंग दें, ताकि आउटलाइन उसे न छुए.
/* Gradient outline with a see-through middle */
.ring {
padding: 0.2em 0.75em; /* Example values: enough room that the outline does not touch the text */
/* The border width is the visible outline thickness. Relative to the font size, with a 2px
minimum so it stays visible on small text; example value. */
border: var(--ring-width, max(2px, 0.12em)) solid transparent;
background: linear-gradient(135deg, var(--ring-start, #2563eb), var(--ring-end, #db2777)) border-box;
/* Paint the background only under the border, so the inside stays transparent. */
background-clip: border-area;
}
/* Border that follows a shape that border-radius cannot draw, such as a tag with a pointed end */
.tag {
padding: 0.2em 1.5em 0.2em 0.9em; /* Example values: extra room at the point so the text is not clipped */
border: var(--shape-stroke, max(2px, 0.08em)) solid var(--shape-color, currentColor); /* Example stroke width */
/* A single shape strokes along its path. Two shapes fill the area between them.
This polygon is an example; use shape() for curves. */
border-shape: polygon(0 0, 85% 0, 100% 50%, 85% 100%, 0 100%);
}
border-shape सिर्फ़ बॉर्डर को बदलता है. बैकग्राउंड अब भी रेक्टैंगल बॉक्स है. इसलिए, किसी शेप को भरने के लिए इस पर भरोसा न करें.
जब सिर्फ़ किनारों को अलग शेप देनी हो, जैसे कि बेवल, स्कूप या नॉच वाला लेबल, तो corner-shape के साथ border-radius का इस्तेमाल करें. यह बैकग्राउंड और बॉर्डर को कोनों के हिसाब से रखता है. साथ ही, जिन ब्राउज़र पर यह सुविधा काम नहीं करती वे सामान्य गोल कोनों पर वापस चले जाते हैं.
.label {
padding: 0.2em 0.9em; /* Example values */
border: var(--shape-stroke, max(2px, 0.08em)) solid var(--shape-color, currentColor);
border-radius: 0.6em; /* Corner size; example value */
corner-shape: bevel; /* round (default) | scoop | bevel | notch | square | squircle */
}
कोई तकनीक चुनें
text-decoration(लाइन, इंक स्किपिंग, स्पेस, इनसेट): लाइन, टेक्स्ट के साथ चलनी चाहिए, उसके साथ रैप होनी चाहिए, और उसकी फ़ॉन्ट मेट्रिक का पालन करना चाहिए. यह डिफ़ॉल्ट विकल्प है.border-shapeऔरclip-pathके साथ सूडो-एलिमेंट: लाइन एक कस्टम शेप है या उसे ड्रॉ-ऑन ऐनिमेशन की ज़रूरत है. इसे सिर्फ़ तब चुनें, जबtext-decoration-styleसे मनमुताबिक लुक न मिल पाए, क्योंकि इसके लिए अतिरिक्त पोज़िशनिंग की ज़रूरत होती है.background-clip: border-area: टेक्स्ट में ग्रेडिएंट आउटलाइन की ज़रूरत है. जब सॉलिड आउटलाइन काफ़ी हो, तब सामान्यborder-colorका इस्तेमाल करें.corner-shape: सिर्फ़ किनारों को अलग शेप देने की ज़रूरत है. जैसे, बेवेल्ड, स्कूप या नॉच. इसेborder-radiusके साथ जोड़ें, जो कोने का साइज़ सेट करता है.border-shape: आउटलाइन के लिए ऐसा शेप चाहिए जिसेborder-radiusड्रॉ नहीं कर सकता. जैसे, टैग या ऐरो. जब गोल कोने काफ़ी हों, तबborder-radiusका इस्तेमाल करें.- इनसेट होवर रिवील: इसे तब जोड़ना चाहिए, जब किसी लिंक पर कर्सर घुमाने पर, रंग बदलने के अलावा कोई और बदलाव भी दिखाना हो. ऐसे टेक्स्ट को स्किप करें जो इंटरैक्टिव नहीं है.
फ़ॉलबैक रणनीतियां
हर फ़ॉलबैक, टेक्स्ट को पढ़ने लायक बनाए रखता है और मुख्य सजावट को बनाए रखता है. ज़रूरत को अपने Baseline टारगेट के हिसाब से तय करें: अगर इसमें बिना प्रॉपर्टी वाले ब्राउज़र शामिल हैं, तो मैच होने वाला फ़ॉलबैक लागू करें.
इंक स्किप करना all
अगर आपका Baseline टारगेट text-decoration-skip-ink: all के साथ काम नहीं करता है, तो एलान को अनदेखा कर दिया जाता है. साथ ही, ब्राउज़र auto को बनाए रखता है. लैटिन वर्णों के डिसेंडर अब भी स्किप किए जाते हैं. सिर्फ़ ऐसी स्क्रिप्ट के लिए इंक स्किप करने की सुविधा काम नहीं करती जो auto में शामिल नहीं हैं. जैसे, जैपनीज़. यह ग्रेसफ़ुल डिग्रेडेशन है. इसलिए, किसी अतिरिक्त कोड की ज़रूरत नहीं है.
स्पेस को स्किप करना
अगर आपका बेसलाइन टारगेट text-decoration-skip-spaces के साथ काम नहीं करता है, तो ब्राउज़र स्पेस को मैनेज करने के लिए अपने डिफ़ॉल्ट तरीके का इस्तेमाल करता है. इसे ग्रेसफ़ुल डिग्रेडेशन कहते हैं: लाइन उन स्पेस के नीचे खींची जाती है जिन्हें ब्राउज़र स्किप नहीं करता.
इनसेट
अगर आपका बेसलाइन टारगेट text-decoration-inset के साथ काम नहीं करता है, तो एलान को अनदेखा कर दिया जाता है. इसलिए, लिंक अपनी सामान्य, पूरी तरह से दिखने वाली अंडरलाइन को बनाए रखता है और ट्रांज़िशन में ऐनिमेट करने के लिए कुछ नहीं होता. इसे अनुकूल गिरावट कहते हैं: कर्सर घुमाने पर दिखने वाला टेक्स्ट हट जाता है और लिंक के नीचे लाइन बनी रहती है.
बॉर्डर एरिया
अगर आपका बेसलाइन टारगेट background-clip: border-area के साथ काम नहीं करता है, तो एलान को अनदेखा कर दिया जाता है. साथ ही, बैकग्राउंड पूरे बॉर्डर बॉक्स के नीचे पेंट हो जाता है. इससे सिर्फ़ आउटलाइन के बजाय टेक्स्ट भर जाता है. अगर डिज़ाइन में ग्रेडिएंट का इस्तेमाल किया गया है, तो सॉलिड बॉर्डर का इस्तेमाल न करें. इसके बजाय, ग्रेडिएंट को फिर से बनाएं और background-clip: border-area को सिर्फ़ @supports के अंदर लागू करें.
जब एलिमेंट का बैकग्राउंड एक ही रंग का हो, तो ओपेक लेयर का इस्तेमाल करें. पैडिंग बॉक्स पर सतह का रंग और बॉर्डर बॉक्स के नीचे ग्रेडिएंट पेंट करें, ताकि ग्रेडिएंट सिर्फ़ पारदर्शी बॉर्डर से दिखे:
.ring {
border: var(--ring-width, max(2px, 0.12em)) solid transparent; /* Example width */
/* Fallback: an opaque surface layer hides the gradient inside the border. */
background:
linear-gradient(var(--surface, canvas) 0 100%) padding-box,
linear-gradient(135deg, var(--ring-start, #2563eb), var(--ring-end, #db2777)) border-box;
}
@supports (background-clip: border-area) {
.ring {
background: linear-gradient(135deg, var(--ring-start, #2563eb), var(--ring-end, #db2777)) border-box;
background-clip: border-area; /* The inside stays transparent */
}
}
जब अंदरूनी हिस्से को पारदर्शी रखना हो, तब मास्क किए गए सूडो-एलिमेंट का इस्तेमाल करें. स्यूडो-एलिमेंट में ग्रेडिएंट होता है और मास्क, पैडिंग रिंग को छोड़कर बाकी सब कुछ काट देता है:
@supports not (background-clip: border-area) {
.ring {
position: relative;
border-color: transparent;
}
.ring::before {
content: "";
position: absolute;
inset: calc(var(--ring-width, max(2px, 0.12em)) * -1); /* Cover the border box */
padding: var(--ring-width, max(2px, 0.12em)); /* Ring thickness */
border-radius: inherit;
background: linear-gradient(135deg, var(--ring-start, #2563eb), var(--ring-end, #db2777));
/* Keep only the area between the content box and the border box. */
mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
mask-composite: exclude;
pointer-events: none;
}
}
बॉर्डर का आकार
अगर आपका Baseline टारगेट border-shape के साथ काम नहीं करता है, तो एलान को अनदेखा कर दिया जाता है और एलिमेंट का बॉर्डर रेक्टैंगल ही रहता है. गोल कोनों वाला रेक्टैंगल, फ़ॉलबैक के तौर पर सिर्फ़ तब स्वीकार किया जाता है, जब आकार पूरी तरह से सजावटी हो. जब किसी आकार का कोई मतलब हो, जैसे कि टैग, ऐरो या कॉलआउट, तो उसे जितना हो सके उतना सटीक बनाएं. साथ ही, border-shape को सिर्फ़ @supports के अंदर लागू करें.
क्लिप किए गए सूडो-एलिमेंट की मदद से आउटलाइन बनाएं. बॉर्डर को पारदर्शी रखें, ताकि बॉक्स का साइज़ उतना ही रहे जितना कि काम करने वाले केस में होता है. सूडो-एलिमेंट को आउटलाइन के रंग से भरें और उसे evenodd clip-path के साथ रिंग में काटें: बाहरी आकार, फिर स्ट्रोक की चौड़ाई के हिसाब से वही आकार इनसेट करें.
.tag {
--stroke: max(2px, 0.08em); /* Example stroke width */
position: relative;
padding: 0.2em 1.5em 0.2em 0.9em; /* Example values */
border: var(--stroke) solid transparent;
}
@supports not (border-shape: circle(50%)) {
.tag::before {
content: "";
position: absolute;
inset: calc(var(--stroke) * -1); /* Cover the border box */
background: var(--shape-color, currentColor);
pointer-events: none;
/* Outer shape, then the inner shape inset by the stroke. The inner points are approximate on
diagonal edges, so the stroke looks slightly thinner there. */
clip-path: polygon(evenodd,
0 0, 85% 0, 100% 50%, 85% 100%, 0 100%,
var(--stroke) var(--stroke),
calc(85% - var(--stroke)) var(--stroke),
calc(100% - var(--stroke) * 2) 50%,
calc(85% - var(--stroke)) calc(100% - var(--stroke)),
var(--stroke) calc(100% - var(--stroke)));
}
}
@supports (border-shape: circle(50%)) {
.tag {
border-color: var(--shape-color, currentColor);
border-shape: polygon(0 0, 85% 0, 100% 50%, 85% 100%, 0 100%);
}
}
अगर आपको आउटलाइन के बजाय, भरी हुई आकृति चाहिए, तो एलिमेंट पर सीधे उन्हीं पॉइंट के साथ clip-path: polygon(...) डालें.
स्यूडो-एलिमेंट अंडरलाइन के लिए, .draw::after पर border-block-end की मदद से एक सीधी लाइन बनाएं. साथ ही, block-size, border, और border-shape स्क्विगल को सिर्फ़ @supports (border-shape: circle(50%)) के अंदर लागू करें. लाइन सीधी है, लेकिन फिर भी ड्रॉ होती है, क्योंकि clip-path ऐनिमेशन, शेप पर निर्भर नहीं करता.
clip-path, फ़ोकस रिंग और box-shadow को भी क्लिप करता है. क्लिप किए गए एलिमेंट पर फ़ोकस दिखाने के लिए, आउटलाइन पर भरोसा न करें. इसके बजाय, :focus-visible को रंग या बैकग्राउंड बदलकर स्टाइल करें.