Please Give Me Some Space

There’s all kinds of ways to do that. Some more advisable and better-suited for certain situations than others, of course.

We could do it directly in HTML:

<p>We go from one line...<br><br> down a couple more.</p>

But that’s what CSS is really for:

<p>We go from one line...<span>down a couple more.</span></p>
span {
  display: block;
  margin-block-start: 1.5rem;
}

Line height can also give us extra breathing room between lines of text:

p {
  line-height: 1.35;
}

Since we’re talking text, there’s also letter-spacing and word-spacing, not to mention text-indent:

But let’s talk boxes instead of text. Say we have two simple divs:

<div>Twiddle Dee</div>
<div>Twiddle Dum</div>

Those are block-level so they’re already on different lines. We can reach for margin again. Or we could create the impression of space with padding. I suppose we could translate those suckers in either direction:

div:nth-child(2) {
  transform: translateY(100px);
}

But maybe those elements are absolutely positioned so we can use physical offsets:

div {
  position: absolute;
}
div:nth-child(1) {
  inset: 0;
}
div:nth-child(2) {
  inset-inline-start: 100px; /* or top: 100px; */
}

If we’re working in a grid container, then we get gap-age:

<section>
  <div>Twiddle Dee</div>
  <div>Twiddle Dum</div>
</section>
section {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 100px;
}

Same deal with a flexible container:

section {
  display: flex;
  gap: 100px;
}

While we’re working in grid and flexible containers, we could call on any alignment property to generate space.

section {
  display: flex;
  align-items: space-between;
  justify-content: space-between;
}

There are tables, of course:

<table cellspacing="100">
  <!-- etc.  -->
  <tbody>
    <tr>
      <td>Twiddle Dee</td>
      <td>Twiddle Dum</td>
    </tr>
  </tbody>
</table>

Or the CSS-y approach:

/* We could use `display: table` if we're not working in a table element. */
table {
  border-spacing: 100px;
}

Let’s go deeper into left field. We can make one element look like two using a linear gradient with a hard color stop:

div {
  background-image:
    linear-gradient(
      to right,
      rgb(255 105 0 / 1) 50%,
      rgb(207 46 46 / 1) 50%,
      rgb(207 46 46 / 1) 100%
    );
}

Then we do a head fake and insert a hard transparent color stop between the two colors:

As long as we’re fakin’ bacon here, might as well toss in the ol’ “transparent” border trick:

Let’s go back to text for a moment. Maybe we’re floating an element and want text to wrap around it… in the shape of the floated element while leaving some space between the two. We have shape-margin for that:

Dare I even mention the spacer.gif days?

<div>Twiddle Dee</div>
<img src="spacer.gif"> <!-- 🤢 -->
<div>Twiddle Dum</div>

There’s gotta be more

You’re all a smart bunch with great ideas. Have at it!


Please Give Me Some Space originally published on CSS-Tricks. You should get the newsletter.

CSS Individual Transform Properties in Safari Technology Preview

In CSS, some properties have shorthand. One property that takes separated values. Syntactic sugar, as they say, to make authoring easier. Take transition, which might look something like:

.element {
  transition: border 0.2s ease-in-out;
}

We could have written it like this:

.element {
  transition-property: border;
  transition-duration: 0.2s;
  transition-timing-function: ease-in-out;
}

Every “part” of the shorthand value has its own property it maps to. But that’s not true for everything. Take box-shadow:

.element {
  box-shadow: 0 0 10px #333;
}

That’s not shorthand for other properties. There is no box-shadow-color or box-shadow-offset.

That’s where Custom Properties come to save us!

We could set it up like this:

:root {
  --box-shadow-offset-x: 10px;
  --box-shadow-offset-y: 2px;
  --box-shadow-blur: 5px;
  --box-shadow-spread: 0;
  --box-shadow-color: #333;
}

.element {
  box-shadow:
    var(--box-shadow-offset-x)
    var(--box-shadow-offset-y)
    var(--box-shadow-blur)
    var(--box-shadow-spread)
    var(--box-shadow-color);
}

A bit verbose, perhaps, but gets the job done.

Now that we’ve done that, remember we get some uniquely cool things:

  1. We can change individual values with JavaScript. Like:
    document.documentElement.style.setProperty("--box-shadow-color", "green");
  2. Use the cascade, if we need to. If we set --box-shadow-color: blue on any selector more specific than the :root, we’ll override that color.

Fallbacks are possible too, in case the variable isn’t set at all:

.element {
  box-shadow:
    var(--box-shadow-offset-x, 0)
    var(--box-shadow-offset-y, 0)
    var(--box-shadow-blur, 5px)
    var(--box-shadow-spread, 0)
    var(--box-shadow-color, black);
}

How about transforms? They are fun because they take a space-separated list of values, so each of them could be a custom property:

:root {
  --transform_1: scale(2);
  --transform_2: rotate(10deg);
}

.element{
  transform: var(--transform_1) var(--transform_2);
}

What about elements that do have individual properties for their shorthand, but also offer comma-separated multiple values? Another great use-case:

:root {
  --bgImage: url(basic_map.svg);
  --image_1_position: 50px 20px;
  --image_2_position: bottom right;
}

.element {
  background: 
    var(--bgImage) no-repeat var(--image_1_position),
    var(--bgImage) no-repeat var(--image_2_position);
}

Or transitions?

:root {
  --transition_1_property: border;
  --transition_1_duration: 0.2s;
  --transition_1_timing_function: ease;
  
  --transition_2_property: background;
  --transition_2_duration: 1s;
  --transition_2_timing_function: ease-in-out;
}

.element {
  transition: 
    var(--transition_1_property) 
    var(--transition_1_duration) 
    var(--transition_1_timing_function),
    var(--transition_2_property) 
    var(--transition_2_duration) 
    var(--transition_2_timing_function),
}

Dan Wilson recently used this kind of thing with animations to show how it’s possible to pause individual animations!


Here’s browser support:

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

ChromeFirefoxIEEdgeSafari
4931No169.1

Mobile / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
8783819.3


The post CSS Individual Transform Properties in Safari Technology Preview appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Robust Exception Handling

Oh no, don't do this to me...

// Writing comment that exception is skipped
try {
    throw new IOException("Made up");
} catch (IOException e) {
    // skip it
}

// Logging and moving on
try {
    throw new IOException("Made up");
} catch (IOException e) {
    log.error("blah blah blah", e);
}

// Creating TODO instead of actually doing the job
try {
    throw new IOException("Made up");
} catch (IOException e) {
    // TODO - handler it (;
}