Is it possibly to keep vertical rhythm using only

2020-02-17 11:13发布

问题:

I'm developing a typography oriented wordpress theme[1], and I'm getting troubles with the in-line images.

I can control every element and adjust it's line height, bottom margin, ecc, to keep the vertical rhythm. But since images pasted through the editor can have any height, they obviously disrupt all the following content.

So the question is if it's possible using margin, padding, both or another solution, to make sure that independent of the image size it will adjust to the baseline.

I know there are some alternatives like make all images turn to a multiple of the line height, that way I can keep the rhythm. Other option would be use javascript, not ideal, but if there's no css solution, I'll have to consider it.

[1] As you can see, this is a css related issue rather than a wordpress one, that's why I'm posting this question here.

回答1:

(edited -- new and improved solution)

I don't know if WordPress provides any way to generate wrapper divs around images, but if it does, then this should work. It is fairly robust in the face of different text scales and image sizes, though you may need to adjust the length of the generated-content string of alternating spaces and non-breaking spaces, depending on how tall or short your images tend to be.

The way this works is that it uses a negative margin to make the outer image wrapper just enough wider than the inner wrapper, so that one non-breaking space will fit on one line before a wrap will occur, and then it generates a string of alternating non-breaking and normal spaces that fills up one line at a time down the right edge, before spilling onto the line below. Finally, a negative margin equal to one line-height counteracts the partially-filled line of spaces below the image.

<!DOCTYPE html>
<html>
  <style>
    .html {
        line-height: 1.25em;
    }
    .p {
        margin: 0;
        padding: 0;
    }
    .section,
    .imginner {
        width: 20em;
    }
    .section {
        float: left;
        margin: 0.5em;
        background-color: #eeeeff;
    }
    .fakeimage {
        background-color: #ffeeee;
    }
    .imgouter {
      margin-right: -0.5em;
      background-color: #eeffee;
      margin-bottom: -1.25em; /* minus 1 line-height */
    }
    .imgouter:after {
        content:'\00a0  \00a0  \00a0  \00a0  \00a0  \00a0  \00a0  \00a0  \00a0  \00a0  \00a0  \00a0  \00a0  \00a0  \00a0  \00a0  \00a0  \00a0  \00a0  \00a0  \00a0  \00a0  \00a0  \00a0'
    }
    .imginner {
      float: left;
      background-color: #ffffdd;
    }
  </style>
<head>
</head>
<body>
  <div class='section'>
    Some text text text text text text.
    Some text text text text text text.
    <div class='imgouter'>
      <div class='imginner'>
        <div class='fakeimage' style="width:145px; height:92px">
          (image here)
        </div>
      </div>
    </div>
    Some text text text text text text.
    Some text text text text text text.
    Some text text text text text text.
  </div>
  <div class='section'>
    Some text text text text text text.
    Some text text text text text text.
    Some text text text text text text.
    Some text text text text text text.
    Some text text text text text text.
    Some text text text text text text.
    Some text text text text text text.
    Some text text text text text text.
    Some text text text text text text.
    Some text text text text text text.
    Some text text text text text text.
    Some text text text text text text.
    Some text text text text text text.
    Some text text text text text text.
  </div>
</body>
</html>


回答2:

I cannot guarantee that any of this will work, but it may be worth a try:

If you can guarantee that all images heights are specified in em, you can set the font-size of the img elements to be the same as the line-height to make sure that all properly inserted images are sized properly:

html
{
  font-size: 15px;
  line-height: 18px;
}

img
{
  font-size: 18px;
  line-height: 18px;
}

Alternatively, you can try floating images within paragraphs so that the image is wrapped with correct rhythm.

<p><img ... /> Lorem ipsum dolor sit amet...</p>

And finally, the pure CSS you'd-have-to-be-crazy-to-implement-this method:

  1. Calculate the line-spacing you're using
  2. Make sure it comes out to a whole pixel (otherwise this will never work).
  3. Make sure all heights are specified uniformly: <img height="100" vs <img height="100px"
  4. Write an obscene number of CSS rules:
img[height$="1"]
{
  margin-bottom: 9px;
}
img[height$="2"]
{
  margin-bottom: 8px;
}
...etc...

Note, this works just fine for 10, and other multiples of 10 and 5, but it'll be a royal pain for pretty much everything else.



回答3:

@PaBLoX, I believe it is entirely possible to achieve vertical rhythm using only CSS. The real question is, "can you create a reusable vertical-rhythm boilerplate using only CSS?". Every project is different, uses different font families, etc. Although vertical rhythm is supposed to be based on math driven by inputs, the variables change with each project. You might not need "blog-style" vertical rhythm on a shopping site...

In any case, it's been a while since this question was asked, but if you or anyone else wants to see an example (attempt) at creating a boilerplate for vertical-rhythm, here is the repo on github: https://github.com/jonschlinkert/vertical-rhythm

It's a starting point. I suspect the project will eventually consist of a few different boilerplates for different needs.



回答4:

In my opinion a pure css soluition is impossible. Take for instance a table. A table cell has by default a little bit of padding so it's content is readable. You could try and make each table cell exactly the right height, but that will be hard. Also, adding for instance a bottom border somewere will also add to the height of the element, which means you have to reckon with it. I love the way that Compass's vertical rhythm tools help maintain a vertical rhythm, but for inline images and for instance tables I found that pure CSS is lacking. For that reason I wrote a simple jquery plugin that could help with this, find it here: https://github.com/dagomar/rhythm.js

Only drawback is that for inline elements to work, it will need an offset, I haven't figured out yet if that can be automated. The offset you can only find by testing it out, I found that an offset of 6 (default) works the best for baselines from 21-24 pixels, but it may be that font-size has an influence. For now, as a proof of concept I found that it works extremely well. It works also for responsive images (window.resize). Hope this helps.



回答5:

If you want to do this purely with CSS, then you have to know the size of each image ahead of time. For example, in this demo:

I have a 20px grid, and the image has a height of 150px, so I have wrapped the image in a container with a height of 160px. This requires extra markup:

<div class=figure>
  <div class=image-wrap style="height:160px">
    <img width=150 height=150>
  </div>
  <p class=caption>Figure 1
</div>

Perhaps such markup could be generated by a WordPress plugin, which receives the image markup and the minimum height and outputs a grid-aligned div wrapper. (I am unfamiliar with WordPress.)

The alternative would be to use JavaScript, which has been addressed in this similar question.



回答6:

I'd suggest using a CSS framework like Foundation or Bootstrap and Compass+SCSS to help with this. I've actually done some work to setup Foundation with a decent default set of Vertical Rhythm rules, which you can use straight out of the box. I have a blog post up which explains it and has a link to a pull-request on Github.

http://lucisferre.net/2012/10/08/getting-into-vertical-rhythm/

With that you can generate some decent base CSS for your typography and other page elements. Or you can just apply the technique to your existing CSS. It's a bit tedious but it isn't all that hard.