2

Trying to archive something like this. Very important for me is, to maintain the aspect ratio of the tilt. Didnt archive this with clip-path or shape-outside. Please help me - this shit driving me crazy. The HTML code looks like this

<div class="wrapper">
<p>text text text text text text text text text text text</p>
</div>

Example of what iam trying to achieve.

I thought of an solution for that but didnt achieve it. Just counting the lines in the text through js and then applying a margin in dependence of line height etc in front of the line to get this done. Thank you.

gustav
  • 336
  • 3
  • 12
  • [This question](https://stackoverflow.com/questions/10271438/reset-angle-of-text-in-skewed-div-using-css) may help you – Joe B. Aug 05 '17 at 01:52
  • Please include a short code-example. – sba Aug 05 '17 at 01:57
  • @JoeB. The text should be upright and not skewed. Just need the alignment to the bounding box – gustav Aug 05 '17 at 02:04
  • @sba didnt come very far with my js solution cause I can't find any line counting script :-( but I will include the html markup – gustav Aug 05 '17 at 02:07
  • Please follow the suggestion my @JoeB. I checked it, and that's pretty much what you are looking for. I guess – Dhaval Jardosh Aug 05 '17 at 02:12
  • [Is this what you want?](http://jsfiddle.net/89x4d/626/) – Dhaval Jardosh Aug 05 '17 at 02:17
  • @DhavalJardosh no it's actually not. In his example the text is getting skewed too. But if u unskew the text, the text doesn't align anymore with the parent element – gustav Aug 05 '17 at 02:17
  • hmm when I try it out myself it seems to look very similar to the example you provided. [DEMO](https://jsfiddle.net/bonez0607/n3qo0tfg/) – Joe B. Aug 05 '17 at 02:21
  • @DhavalJardosh that's it. But the problem there is that every line have to be a own paragraph, isn't it? – gustav Aug 05 '17 at 02:22
  • Yes, I am trying to put another container inside and trying to get to what you are looking for. – Dhaval Jardosh Aug 05 '17 at 02:23
  • @DhavalJardosh another thought of mine was to add another div inside and applying a polygon outside shape to it and floating it left. Problem was that it isn't responsive to the height of the div and looses the tilt ratio – gustav Aug 05 '17 at 02:28
  • [This is where I have reached so far](https://jsfiddle.net/n3qo0tfg/3/), trying to tilt the inner text. – Dhaval Jardosh Aug 05 '17 at 02:35
  • @DhavalJardosh yea but it's not a solution for me. Seems like there is no way to solve this – gustav Aug 05 '17 at 12:40
  • [i found this one here](https://www.sarasoueidan.com/blog/css-shapes/) what is exact what i mean and tested. The only Problem is that the floating div is not responsive. To achieve a constant angle of, for example 11 deg, the div has to stay his aspect ratio.. someone a idea? – gustav Aug 05 '17 at 14:13

2 Answers2

1

The problem you are hitting in to, when de-skewing only one <p> element is that element will always be treated as a square block. Meaning that each new line renders vertically down, rather than following the skewed edge of the parent. To get around this, you just need to break up the paragraph into smaller individual inline blocks.

Doing this manually is not great, which is why I would recommend a layer of script to do it (which should be easy to put together using a cross-browser lib, and something that can target TextNodes e.g. How do I select text nodes with jQuery?). However, you also wouldn't want to use this approach for large amounts of text — as it will incur a lot of processing for the browser. Both in CSS and JS:

.skew {
  width: 400px;
  transform: skew(-20deg);
  background: red;
}
    
.skew > span {
  display: inline-block;
  transform: skew(20deg);
}
<div class="skew">
<span>This</span> <span>is</span> <span>lots</span> 
<span>of</span> <span>text</span>. <span>This</span> 
<span>is</span> <span>lots</span> <span>of</span> 
<span>text</span>. <span>This</span> <span>is</span> 
<span>lots</span> <span>of</span> <span>text</span>.
<span>This</span> <span>is</span> <span>lots</span> 
<span>of</span> <span>text</span>. <span>This</span> 
<span>is</span> <span>lots</span> <span>of</span> 
<span>text</span>. <span>This</span> <span>is</span> 
<span>lots</span> <span>of</span> <span>text</span>.
<span>This</span> <span>is</span> <span>lots</span> 
<span>of</span> <span>text</span>. <span>This</span> 
<span>is</span> <span>lots</span> <span>of</span> 
<span>text</span>. <span>This</span> <span>is</span> 
<span>lots</span> <span>of</span> <span>text</span>.
</div>

The other downside to the approach is that once you have broken things up, you can no longer rely on wrapping block elements for padding/margin. You can obviously still handle vertical spacing using specifically placed block elements i.e. headers or specific classes. E.g.

<h1>Title</h1>
<span>Word</span> <span>word</span> <span>word</span>
<span class="break"></span>
<span>Word</span> <span>word</span> <span>word</span>

So not an ideal solution either, but at runtime it does only require CSS, which is a positive.

It would be great if more things supported shape-outside

https://developer.mozilla.org/en/docs/Web/CSS/shape-outside

Unfortunately the CSS shapes specification seems to be taking a while to be implemented.

https://www.w3.org/TR/css-shapes-1

Pebbl
  • 34,937
  • 6
  • 62
  • 64
  • yea, just realised that shape-outside has very little browser support. feels bad man. I need that for a client - he has a CD that includes non-rectangular textboxes.. :-( I use a cms so i can break the paragraph up server side.. would be that a performance killer client side? – gustav Aug 05 '17 at 22:45
  • @Karl You'll only incur the CSS processing on the client if you've already broken the words up server side (which would def. be better)... and tbh browsers are pretty performant these days with CSS processing. It just won't render as quickly as a standard text layout is all, but you'd have to hit a large amount of text/elements to cause a modern useragent visible issues. So the solution is not ideal, but I don't really see a better alternative right now... been waiting for css shapes myself for a while. – Pebbl Aug 05 '17 at 23:02
  • so i will break the words server side up and tryin to get the best result i can. Thank you for your help – gustav Aug 05 '17 at 23:11
  • do u have an idea how to achieve this "wrapping" of every word in a span tag? I use PHP server-side and [tried to use regex](https://stackoverflow.com/questions/45572090/regex-wrap-every-word-in-a-span-tag/45572144#45572144) but didnt it make it perfectly. – gustav Aug 09 '17 at 20:36
  • @Karl Yes, you can modify the answer I gave here on another SO question. https://stackoverflow.com/questions/5956610/how-to-select-first-10-words-of-a-sentence/12445298#12445298 . But it does all depend on what format your content is in. Usual rule would be to use a RegExp, but try to aim for the things that are easier to reason about i.e. the gaps between words, rather than the words themselves. Once you have an array of words, it should be easy to recombine them with wrappers. – Pebbl Aug 10 '17 at 13:00
  • the point is, that i get the content with html tags such as

    or

    . So i have wrap every word in a span but also maintain the html tags.

    – gustav Aug 11 '17 at 22:08
  • @Karl — That means things get a whole lot more complicated. For that work you will definitely need to employ a DOM parser... but as soon as you start doing that, you might as well do the parsing and word replacing in the client, because that is what they are good at. Unless you can cache the result of adding the additional in the server, in which case it is still worth doing server-side. Either way, it isn't so simple if your content is already a text/html mix. – Pebbl Aug 12 '17 at 19:41
  • Year. Using the CMS GRAV i hope that will find a solution for that. Thank you – gustav Aug 12 '17 at 20:49
0

I finally got it.

No cross browser support :-(

Here is my solution - its not perfect at all.

The only thing here is, that the angle is not equal. You can see that the margin between the .text and the outer .text_content is not equal from top to bottom. I dont know why, cause math never lies :-P

  • First step is to add a element .angle next to the text wrapper .text with float:left;.
  • Second step get the height from the text wrapper .text and give the same value to the height and width to the element .angle with js. The .angle element responds now to the length of the text.
  • Third step give that .angle element now a polygon in shape-outside and use this formular tan(α) * a = b to get the right coordinate for the polygon point. Now the .angle element lets the text float around it.

For the outer .text_content its pretty much the same. But instead of shape-outside use clip-path to hide the overflow.

ps: iam sorry for my bad english, done my best. ;-)

function angle_text() {
      var angle_deg = 11;
      var angle_rad = angle_deg * Math.PI/180; 
      //converting to rad
      var height_of_text = $('.text_content .text').height(); 
       //get the height of the text -> including h1 and p
      $('.text_content .angle').height(height_of_text); 
      //setting the height and width of the triangle element equally
      $('.text_content .angle').width(height_of_text);

      var b = Math.tan(angle_rad) * height_of_text; 
      // tan(a) x a = b - width of the triangle polygon in px
      $('.text_content .angle').css('shape-outside', 'polygon(0 0, '+b+'px 0, 0% 100%)') 
      //setting polygon as shape to float text
      $('.text_content .angle').css('clip-path', 'polygon(0 0, '+b+'px 0, 0% 100%)') 
      //setting polygon as path to see the triangle


      var height_of_content = $('.text_content').height(); 
      //get height of the whole block
      var b = Math.tan(angle_rad) * height_of_content; 
      // tan(a) x a = b - width of the triangle polygon in px
      $('.text_content').css('clip-path', 'polygon('+b+'px 0, 100% 0, 100% 100%, 0% 100%)') 
      //setting polygon as path to hide the overflow
  }
  angle_text(); //call function on site ready

  $(window).resize(function() { //call function on window resize
    angle_text();
  });
.text_content {
      margin: 2rem 0;
      color: #fff;
      vertical-align: top;
      text-align: left;
      width: 50%;
      padding:2rem;
      word-wrap: normal;
      line-height: 1.5rem;
      box-sizing:border-box;
      float: right;
      position: relative;
      background: blue;

}
      .angle {

        background: green;
        float:left;

      }
      p {

        margin: 1rem 0;
        font-style:italic;
        
      }

      h1 {
        font-size:2rem;
        line-height:2rem;
        margin: 0;
      }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="text_content" >
  <div class="angle">
  </div>
  <div class="text">
    <h1>Hey Guys</h1>
    <p>Stackoverflow text Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
  </div>
</section>
gustav
  • 336
  • 3
  • 12