-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #32 from HyunmoAhn/docs/line-spacing
Docs/line spacing
- Loading branch information
Showing
14 changed files
with
2,235 additions
and
119 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
...usaurus-plugin-content-blog-trouble-shooting/2024-10-31-line-spacing-on-css.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
--- | ||
slug: line-spacing-on-css | ||
title: How to implement line-spacing in CSS | ||
description: Explains how to implement line spacing in CSS | ||
keywords: | ||
- css | ||
- web | ||
authors: HyunmoAhn | ||
tags: [css, line-spacing, web, issue, trouble-shooting, line-height] | ||
--- | ||
|
||
## Introduction | ||
|
||
In CSS, line-height is used to adjust line spacing. However, in a project I worked on, | ||
there was a requirement to support line-spacing. This article explains how to implement line-spacing using CSS. | ||
|
||
import { LinePaddingExample, LinePlayground } from '@site/src/code-snippet/lineSpacing/index.tsx' | ||
|
||
<LinePaddingExample /> | ||
|
||
## Cheat Sheet | ||
|
||
Unlike line-height, which applies padding both above and below the text, line-spacing applies padding only between lines. | ||
The difference here is that line-spacing does not add padding at the beginning and end of the text block. | ||
|
||
You can implement line-spacing using margins. | ||
|
||
```tsx | ||
const lineHeight = 20; // origin line-height | ||
const lineSpacing = 10; | ||
const margin = - (lineSpacing / 2); | ||
|
||
const LineSpacingText = () => { | ||
return ( | ||
<p style={{ | ||
// highlight-start | ||
marginTop: `${margin}px`, | ||
marginBottom: `${margin}px`, | ||
lineHeight: `${lineHeight + lineSpacing}px`, | ||
// highlight-end | ||
}}> | ||
Hello, World! | ||
</p> | ||
); | ||
}; | ||
``` | ||
|
||
|
||
## Playground | ||
<LinePlayground /> | ||
|
||
<!--truncate--> | ||
|
||
## Additional Story | ||
|
||
There isn't much more to say about the topic of line-spacing. | ||
If you have the idea of "Can it be implemented in CSS?", it's a difficulty level that can be sufficiently implemented. | ||
|
||
The key to this idea is that while `line-height` applies padding both above and below, `line-spacing` applies padding only between lines. | ||
Therefore, even in the case of `line-height`, the spacing between lines is the same as the `line-spacing` padding, | ||
and the difference is the presence or absence of padding on the first and last lines. | ||
To bridge this difference, you use margins to reduce the value by `line-spacing / 2`. | ||
|
||
In general web development, if such a `line-spacing` requirement comes up, | ||
it is better to somehow persuade in another direction or propose an alternative. | ||
In my case, although it was on the web, I had to create a design tool that perfectly matched a screen developed native, | ||
and I had to satisfy the special specification of `line-spacing`, so I used this method. | ||
It is not recommended to use this method simply to meet design requirements. | ||
Nevertheless, I hope this article helps developers who need to meet similar requirements. | ||
|
||
import { Playground } from '@site/src/components/playground/index.tsx' | ||
import { codeSnippet } from '@site/src/code-snippet/lineSpacing/index.tsx' | ||
|
||
|
||
## Code Playground | ||
|
||
<Playground title={'line-spacing'} files={codeSnippet} height={900} outputHeight={400} /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
import cx from 'classnames'; | ||
import { useState, useId } from 'react'; | ||
import { Select } from '@radix-ui/themes'; | ||
import * as Label from '@radix-ui/react-label'; | ||
import style from './lineSpacing.module.scss'; | ||
import lineSpacingSnippet from '!!raw-loader!./lineSpacingSnippet'; | ||
|
||
const TEXT_SAMPLE = | ||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet.'; | ||
|
||
export const LineSpacingGuide = () => { | ||
return ( | ||
<div className={style.guideWrapper}> | ||
<h4>Line Spacing</h4> | ||
<div className={cx(style.lineSpacingGuideContainer, style.guideContainer)}> | ||
<p>Line Gap</p> | ||
<p className={style.lineSpacingGuide} style={{ backgroundColor: 'red' }} /> | ||
<p>Line Gap</p> | ||
<p className={style.lineSpacingGuide} style={{ backgroundColor: 'green' }} /> | ||
<p>Line Gap</p> | ||
</div> | ||
<p className={style.caption}>Line Spacing (5px)</p> | ||
</div> | ||
); | ||
}; | ||
|
||
export const LineHeightGuide = () => { | ||
return ( | ||
<div className={style.guideWrapper}> | ||
<h4>Line Height</h4> | ||
<div className={cx(style.lineHeightGuideContainer, style.guideContainer)}> | ||
<p className={style.lineHeightGuide} style={{ backgroundColor: 'red' }} /> | ||
<p>Line Gap</p> | ||
<p className={style.lineHeightGuide} style={{ backgroundColor: 'red' }} /> | ||
<p className={style.lineHeightGuide} style={{ backgroundColor: 'green' }} /> | ||
<p>Line Gap</p> | ||
<p className={style.lineHeightGuide} style={{ backgroundColor: 'green' }} /> | ||
<p className={style.lineHeightGuide} style={{ backgroundColor: 'blue' }} /> | ||
<p>Line Gap</p> | ||
<p className={style.lineHeightGuide} style={{ backgroundColor: 'blue' }} /> | ||
</div> | ||
<p className={style.caption}>Line Height (5px)</p> | ||
</div> | ||
); | ||
}; | ||
|
||
export const LinePaddingExample = () => { | ||
return ( | ||
<div className={style.container}> | ||
<LineSpacingGuide /> | ||
<LineHeightGuide /> | ||
</div> | ||
); | ||
}; | ||
|
||
export const LineSpacingPlayground = ({ lineSpacing }: { lineSpacing: number }) => { | ||
const paddingGap = lineSpacing / 2; | ||
|
||
return ( | ||
<div> | ||
<h3>Line Spacing {lineSpacing}px</h3> | ||
<div className={style.playgroundBorder}> | ||
<p | ||
className={style.playground} | ||
style={{ | ||
lineHeight: `${lineSpacing + 26}px`, | ||
marginTop: `-${paddingGap}px`, | ||
marginBottom: `-${paddingGap}px`, | ||
}} | ||
> | ||
{TEXT_SAMPLE} | ||
</p> | ||
</div> | ||
<p className={style.caption}>Line Spacing ({lineSpacing}px)</p> | ||
</div> | ||
); | ||
}; | ||
|
||
export const LineHeightPlayground = ({ lineHeight }: { lineHeight: number }) => { | ||
return ( | ||
<div> | ||
<h3>Line Height ({lineHeight}px + fontSize)</h3> | ||
<div className={style.playgroundBorder}> | ||
<p className={style.playground} style={{ lineHeight: `${lineHeight + 26}px` }}> | ||
{TEXT_SAMPLE} | ||
</p> | ||
</div> | ||
<p className={style.caption}>Line Height ({lineHeight}px + fontSize)</p> | ||
</div> | ||
); | ||
}; | ||
|
||
export const SpacingSelect = ({ | ||
value, | ||
onChange, | ||
}: { | ||
value: number; | ||
onChange: (value: string) => void; | ||
}) => { | ||
const id = useId(); | ||
|
||
return ( | ||
<div className={style.select}> | ||
<Label.Root htmlFor={id}>Select Spacing</Label.Root> | ||
<Select.Root value={String(value)} onValueChange={onChange}> | ||
<Select.Trigger id={id} /> | ||
<Select.Content> | ||
<Select.Item value="0">0px</Select.Item> | ||
<Select.Item value="5">5px</Select.Item> | ||
<Select.Item value="10">10px</Select.Item> | ||
<Select.Item value="15">15px</Select.Item> | ||
<Select.Item value="25">25px</Select.Item> | ||
<Select.Item value="30">30px</Select.Item> | ||
<Select.Item value="40">40px</Select.Item> | ||
</Select.Content> | ||
</Select.Root> | ||
</div> | ||
); | ||
}; | ||
|
||
export const LinePlayground = () => { | ||
const [value, setState] = useState(0); | ||
|
||
return ( | ||
<div className={style.linePlaygroundWrapper}> | ||
<SpacingSelect value={value} onChange={(selected) => setState(Number(selected))} /> | ||
<div className={style.linePlayground}> | ||
<LineSpacingPlayground lineSpacing={value} /> | ||
<LineHeightPlayground lineHeight={value} /> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export const codeSnippet = { | ||
'/App.js': lineSpacingSnippet, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
.container { | ||
display: flex; | ||
justify-content: space-around; | ||
column-gap: 20px; | ||
} | ||
|
||
.guideWrapper { | ||
display: flex; | ||
flex-direction: column; | ||
} | ||
|
||
|
||
.guideContainer { | ||
display: flex; | ||
flex-direction: column; | ||
justify-content: center; | ||
align-items: center; | ||
line-height: 1; | ||
min-width: 150px; | ||
font-size: 26px; | ||
font-family: serif; | ||
overflow: hidden; | ||
text-align: center ; | ||
|
||
border: 1px solid var(--ifm-color-primary-dark); | ||
border-radius: 5px; | ||
padding: 3px; | ||
|
||
p { | ||
margin: 0; | ||
width: 100%; | ||
} | ||
} | ||
|
||
.caption { | ||
margin-left: 3px; | ||
margin-top: 3px; | ||
font-size: 14px; | ||
font-weight: 500; | ||
color: var(--ifm-color-primary-dark); | ||
} | ||
|
||
.lineSpacingGuide { | ||
height: 10px; | ||
} | ||
|
||
.lineHeightGuide { | ||
height: 5px; | ||
} | ||
|
||
.playgroundBorder { | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
justify-content: center; | ||
font-size: 26px; | ||
border: 1px solid var(--ifm-color-primary-dark); | ||
border-radius: 5px; | ||
padding: 3px; | ||
margin-bottom: 3px; | ||
} | ||
|
||
.playground { | ||
font-size: 26px; | ||
margin-bottom: 0; | ||
|
||
transition: all 0.3s ease; | ||
} | ||
|
||
.linePlayground { | ||
display: flex; | ||
flex-direction: row; | ||
justify-content: space-between; | ||
column-gap: 20px; | ||
} | ||
|
||
.linePlaygroundWrapper { | ||
display: flex; | ||
flex-direction: column; | ||
row-gap: 10px; | ||
} | ||
|
||
|
||
|
||
.select { | ||
display: flex; | ||
justify-content: flex-start; | ||
align-items: center; | ||
column-gap: 10px; | ||
background-color: var(--dark-background-color); | ||
margin-bottom: 10px; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { useState } from 'react'; | ||
|
||
export default function App() { | ||
const [lineSpacing, setLineSpacing] = useState(0); | ||
|
||
return ( | ||
<> | ||
<h3> | ||
Line Spacing:{' '} | ||
<input type="text" value={lineSpacing} onChange={(e) => setLineSpacing(e.target.value)} /> | ||
px | ||
</h3> | ||
<LineSpacingPlayground lineSpacing={Number(lineSpacing)} /> | ||
</> | ||
); | ||
} | ||
|
||
export const LineSpacingPlayground = ({ lineSpacing }) => { | ||
const paddingGap = lineSpacing / 2; | ||
|
||
return ( | ||
<div> | ||
<p | ||
style={{ | ||
width: '200px', | ||
fontSize: '26px', | ||
lineHeight: `${lineSpacing + 26}px`, | ||
marginTop: `-${paddingGap}px`, | ||
marginBottom: `-${paddingGap}px`, | ||
}} | ||
> | ||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. | ||
Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. | ||
</p> | ||
</div> | ||
); | ||
}; |
Oops, something went wrong.