164

I have several same HTML elements going one after another:

<span>1</span>
<span>2</span>
<span>3</span>

I'm looking for the best way of adding space between the elements using CSS only

[no space]  [1]  [space 10px]  [2]  [space 10px]  [3]  [no space]

Additionally:

  • Please write down browser compatibility of your receipts

I don't want to use any additional HTML markup like

<span></span>  <span></span>  <span class="last_span"></span>

I don't want to use tables.

I want the first and last span to be targeted automatically by CSS.

I don't want to use JavaScript.

Optional requirement: last span can be not last child of the parent tag, but it will be the last span of the parent tag. Spans do not have any other tags between them.

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
Dan
  • 55,715
  • 40
  • 116
  • 154

13 Answers13

352

A good way to do it is this:

span + span {
    margin-left: 10px;
}

Every span preceded by a span (so, every span except the first) will have margin-left: 10px.

Here's a more detailed answer to a similar question: Separators between elements without hacks

Community
  • 1
  • 1
thirtydot
  • 224,678
  • 48
  • 389
  • 349
45

Add these rules to the parent container:

display: grid
grid-auto-flow: column
grid-column-gap: 10px

A good reference: CSS Reference - A free visual guide to CSS

Browser compatibility: Browser Support for CSS Grid Layout

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
reddtoric
  • 568
  • 1
  • 6
  • 13
  • 3
    `grid-auto-columns="max-content"` may also be useful. It will make the grid item's size match the content. Also, browser compatibility shouldn't be an issue anymore: https://caniuse.com/#feat=css-grid – Alex Salomon Dec 15 '19 at 21:53
  • This should be the accepted answer. I know comments are not for thanks, i was only making use of the 'flex' display until now, and this 'grid' thing makes it all so easy from the parent container itself! To not leave it entirely useless, would add the following reference that helps a lot for anyone looking to learn more: https://css-tricks.com/snippets/css/complete-guide-grid/ – Rohan Kumar Jun 14 '20 at 09:57
45

Just use margin or padding.

In your specific case, you could use margin:0 10px only on the second <span>.

Here's a nice CSS 3 solution (JSFiddle):

span {
    margin: 0 10px;
}

span:first-of-type {
    margin-left: 0;
}

span:last-of-type {
    margin-right: 0;
}

Advanced element selection using selectors like :nth-child(), :last-child, :first-of-type, etc. is supported since Internet Explorer 9.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Simone
  • 20,302
  • 14
  • 79
  • 103
  • You have a great answer, Simone, but could you please solve the question without specifying the last `span` manually? This should be the CSS's job – Dan Nov 18 '11 at 15:59
  • this is an unneded hack, that's the "word-spacing" property for: http://www.w3schools.com/cssref/pr_text_word-spacing.asp check Ben's answer – arieljuod Nov 22 '13 at 15:29
  • the OP wanted space between spans, so it's ok to give a solution for inline elements, the margin/padding/first/last properties are not needed here and only adds complexity – arieljuod Nov 22 '13 at 17:11
  • Actually, the OP said he'll be using `span`s and `div`s (which are block elements). Your solution is valid anyway if you define `div`s as inline elements... – Simone Nov 23 '13 at 11:26
23

You can style elements with excluding the first one, just in one line of code:

span ~ span {
    padding-left: 10px;
}

There isn't a need to change any classes.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Angie
  • 511
  • 5
  • 17
  • 1
    This one works perfekt. span + span didnt work but span ~ span works like a charm! Thanks – juliusmh Apr 24 '16 at 11:42
  • 1
    In my case, I have several spans, some of which may not contain the class "Showing", so what I need is `span.Showing ~ span.Showing` instead of `span.Showing + span.Showing`. `~` is the general sibling selector, where one doesn't need to directly follow another. – Eric Jan 06 '20 at 07:53
12

You can take advantage of the fact that span is an inline element:

span{
     word-spacing: 10px;
}

However, this solution will break if you have more than one word of text in your span.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ben
  • 121
  • 1
  • 2
9
span:not(:last-child) {
    margin-right: 10px;
}
Vladyslav Savchenko
  • 1,282
  • 13
  • 10
4

If you want to align various items and you like to have the same margin around all sides, you can use the following. Each element within container, regardless of type, will receive the same surrounding margin.

Enter image description here

.container {
  display: flex;
}
.container > * {
  margin: 5px;
}

If you wish to align items in a row, but have the first element touch the leftmost edge of container, and have all other elements be equally spaced, you can use this:

Enter image description here

.container {
  display: flex;
}
.container > :first-child {
  margin-right: 5px;
}
.container > *:not(:first-child) {
  margin: 5px;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Stefan Zhelyazkov
  • 2,599
  • 4
  • 16
  • 41
  • 3
    While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value. – β.εηοιτ.βε Jun 12 '20 at 19:33
4

You can write like this:

span{
    margin-left: 10px;
}

span:first-child{
    margin-left: 0;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
sandeep
  • 91,313
  • 23
  • 137
  • 155
3

You should wrap your elements inside a container, use new CSS 3 features like CSS grid, a free course, and then use grid-gap:value that was created for your specific problem.

span{
  border: 1px solid red;
}
.inRow{
  display: grid;
  grid-template-columns: repeat(auto-fill, auto);
  grid-gap: 10px /* This adds space between elements, only works on grid items */
}
.inColumn{
  display: grid;
  grid-template-rows: repeat(auto-fill, auto);
  grid-gap: 15px;
}
<div class="inrow">
  <span>1</span>
  <span>2</span>
  <span>3</span>
</div>
<div class="inColumn">
  <span>4</span>
  <span>5</span>
  <span>6</span>
</div>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
John Balvin Arias
  • 2,632
  • 3
  • 26
  • 41
2

Or, instead of setting margin and then overriding it, you can just set it properly right away with the following combination:

span:not(:first-of-type) {
    margin-left:  5px;
}

span:not(:last-of-type) {
    margin-right: 5px;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
jalooc
  • 1,169
  • 13
  • 23
  • Good answer, the restriction is the browser support of `:first-of-type` and `:last-of-type` CSS selectors. – Dan Nov 14 '14 at 21:35
  • ...also check for `not` expression browser support – Dan Nov 14 '14 at 21:38
  • 1
    @Dan [it's](http://caniuse.com/#feat=css-sel3) actually great, all several last-years browsers are covered. But I must admit, that yzoja's solution is even smarter :) – jalooc Nov 15 '14 at 21:25
  • This solution is superior in the specific case that you are going to also include borders between elements as separators (so like a UL in a nav, for example), as it will properly place the border in the middle of the spacing. – Mir Apr 06 '15 at 21:38
2

<span> is an inline element, so you can’t make spacing on them without making it block level.

Try this:

Horizontal

span{
    margin-right: 10px;
    float: left;
}

Vertical

span{
    margin-bottom: 10px;
}

It is compatible with all browsers.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Moe Sweet
  • 3,683
  • 2
  • 34
  • 46
0
/* Horizontal space */
.space-8-x > * + * {
    margin-left: 8px;
}
/* Vertical space */
.space-8-y > * + * {
    margin-top: 8px;
}
<div class="space-8-x">
    <span>1</span>
    <span>2</span>
    <span>3</span>
</div>

<div class="space-8-y">
    <div>1</div>
    <div>2</div>
    <div>3</div>
</div>
belykh
  • 1,109
  • 10
  • 25
0
span.middle {
    margin: 0 10px 0 10px; /* top right bottom left */
}
<span>text</span> <span class="middle">text</span> <span>text</span>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Tim Joyce
  • 4,487
  • 5
  • 34
  • 50