【问题标题】:Prefer new lines to long lines喜欢新行而不是长行
【发布时间】:2013-09-09 17:53:19
【问题描述】:

我想控制文本在框中的显示方式,更喜欢新行而不是长行,但仍然允许长行。

这里有一些例子:http://codepen.io/anon/pen/jiCxo

  • 在#1 中,有一个“长”文本和长行。这就是我希望它的行为方式。
  • 在#2 中,有一个短文本和一个长行。我不喜欢它。

我想要:

  • 2 就像 #3 一样,无需手动添加 <br>

  • 对“长”文本和短文本使用相同的 HTML 和 CSS。

另外,我希望第一行最短,而不是最后一行:http://codepen.io/anon/pen/irFcK

有什么想法吗?

(如果我担心只使用 CSS 是不可能的,我愿意接受一个不错的 JavaScript 解决方案)

【问题讨论】:

  • 最多两行吗?
  • 不幸的是,没有。我更喜欢没有最大值的解决方案,但我认为将 4 行作为我的用例的最大值是安全的。
  • 我认为仅使用 CSS 是不可能的...但是让我们看看。
  • 好吧,如果没有其他办法,我会寻找带有一些 JavaScript 的渐进增强解决方案,但我显然更喜欢完整的 CSS 解决方案。关于最大值,我可以看到一个解决方案最多使用 2 条短线,同时允许更多长线(如果有帮助的话)。
  • 你总是想要至少 2 行吗?最少多少字?

标签: javascript css


【解决方案1】:

我做了一个快速的功能,应该做你想做的事。我评论了它,所以你知道发生了什么。

$(".box h1").each(function() {
  // Check if one line
  if($(this).height() <= parseInt($(this).css('line-height'))){
    // Check if width is greater than %50 of parent
    if($(this).width() >= $(this).parent().width()/2){
      // Adjust width to put it on two lines
      $(this).width($(this).parent().width()/2)
    }
  }
});

编辑:

要使第一行比第二行短,您必须做一些更复杂的事情。我使用了 this answer 的剪切。这应该非常接近您想要的。

$(".box h1").each(function() {
  // Check if one line
  if($(this).height() <= parseInt($(this).css('line-height'))){
    // Check if width is greater than %50 of parent
    if($(this).width() >= $(this).parent().width()/2){
      // First find approximately where you want it
      place = Math.round($(this).val().length/2);         // Might need a parseFloat
      // Find nearest end of word in correct direction
      original = $(this);
      first = original.text(cut(place));

      end = first.val().length
      start = $(this).val().length - end
      second = $(this).substr(start,end)

      // Place a break tag in the middle to put it on two lines
      $(this).html(first + <br> + second)
    }
  }
});

剪掉了

function cut(n) {
    return function textCutter(i, text) {
        var short = text.substr(0, n);
        if (/^\S/.test(text.substr(n)))
            return short.replace(/\s+\S*$/, "");
        return short;
    };
}

此代码使用&lt;br&gt; 分隔两行(第二行更长)

编辑2:

如果没有&lt;br&gt; 或其他添加新行的方式,就不可能有不同的行长。如果您更喜欢它,我可以更改它,使其使用多个 &lt;h1&gt; 标签,我认为这会自动将每个添加标签踢到新行

【讨论】:

  • 似乎有效,这是一个快速测试:codepen.io/anon/pen/FmCiE(我对您的代码进行了一些更正,并在 CSS 中添加了 line-height 属性)。
  • 太棒了,我更新了它以包含您的更改(如果我错过了请告诉我!)
  • h1 而不是h3,但这没什么大不了的。但是,在尝试更多示例时,我遇到了一个新问题(与您的解决方案没有特别相关):我希望最短的线是第一个,而不是最后一个。你有解决这个问题的想法吗?
  • 我的意思是我不想手动添加&lt;br&gt;。因为我将使用一些 JavaScript,所以没关系(在我看来,比 &lt;h1&gt; 更好)。谢谢您的回答。它似乎只适用于一两行,但我明天会玩它(这里是UTC+2),如有必要,请尝试扩展它,并让你知道它是如何工作的。
  • 是的,我仍在为 2 行的可能性编码,我修复它以便它可以处理多个
【解决方案2】:

我想出了一个利用still fairly unknown JS library named MediaClass 的解决方案,它可以使用页面上特定元素的媒体查询。

我认为我设置值的方式看起来很不错,但您可能希望通过更改 JS 或 CSS 中的宽度对其进行微调。这是一个 jsFiddle 供您修补乐趣。

它的工作方式:

JS:

MediaClass("large", "h1:media(this-min-width: 300px)");
MediaClass("small", "h1:media(this-min-width: 200px and this-max-width: 300px)");

如果h1 的宽度在200px300px 之间,这些行确保small 类被添加到h1,如果h1300px 宽,则large 类.

CSS:

.large:before {
    content:"\A"; 
    width: 50%;
    display: inline-block;
}
.small:before {
    content:"\A"; 
    width: 30%;
    display: inline-block;
}

这个位添加了一个:before伪元素,其宽度取决于h1h1的宽度,在文本之前,这会将h1内的第一行移到上面,这会改变文本的流动。

编辑:我修复了帖子和小提琴,以更好地展示此解决方案如何回答所提出的问题。

【讨论】:

  • 不幸的是,对于这个用例,我无法让它按我的意愿工作(我讨厌你的 jsFiddle 中的#8)。这就是说,MediaClass 看起来很棒,我一定会记住它,谢谢你的发现。
【解决方案3】:

您需要 JavaScript 来执行此操作。 CSS 无法根据一组复杂的规则来格式化文本。

【讨论】:

    【解决方案4】:

    我认为您不能仅使用 CSS 来做到这一点。这是一个 Javscript sn-p,您可以尝试实现它来解析您的字符串。它笨重且未经测试,但允许您预设所需的字符长度和字长。我相信您可以清理它并使其适合您的需求。

    // requires h1 field to have line-height property set
    $(".box h1").each(function()
    {
      // splits if over this % width
      var preset = 50;
      // indents first line to same as preset percentage
      // to attempt to make first line shorter
      var indent = String(preset) + 'px';
      // height of a standard line
      var lh = parseInt($(this).css('line-height'));
      // width of the box
      var w = $(this).parent().width() * (preset/100);
    
      // if the text field is one line heigh & over the preset
      if(($(this).height() <= lh) && ($(this).width() >= w))
      {
        $(this).width(w);
        $(this).css('text-indent' , indent);
      }
      // otherwise it's fine
    });
    

    这是一个链接:http://codepen.io/jnickg/pen/szIpd

    【讨论】:

    • 这似乎不起作用,我一定遗漏了一些东西:codepen.io/anon/pen/pgKFisplitString.length 似乎总是返回1
    • 我遗漏了一些东西:newString.split(" ") 应该是 aString.split(" ")。尽管如此,即使使用参数,我也无法让它像我想要的那样工作。
    • 它并没有从一开始就准备好运行,因为它没有被写入自动运行。我重写了它,使用了一些其他工作答案的想法,以获得更好的工作解决方案。请让我知道你的想法。
    • 我知道它不是为自动运行而设计的,这就是为什么我在最后添加了一点 jQuery 来在每个盒子上执行它。您的新示例在笔中效果不佳(#2 应该看起来像#3),但我必须说使用text-indent 是一个非常有趣的想法。
    【解决方案5】:

    TMP's answerthis answer 对另一个问题的启发,我想出了这个脚本,它在大多数情况下都很好用,但仍有一些怪癖……

    var minimum_gap = 5; // Minimum gap on the last line to try to put it on the first.
    
    $(".box h1").each(function() {
        var h1 = $(this),
            text = h1.text(),
            words = text.split(' '),
            lines = [],
            first_word = [],
            l = 0,
            i = 0;
    
        // Adding a span to measure the width
        h1.wrapInner('<span>');
        var span = h1.find('span');
    
        // Put the first word in the span and save the height
        span.text(words[0]);
        var height = h1.height();
    
        // Measure width of each line
        for(var i = 1; i < words.length; i++){
            span.append(' ' + words[i]);
    
            // If there's a new line
            if(h1.height() > height){
                lines[l] = span.width();
                span.text(words[i]);
                l++;
            }
        }
        // Last line
        lines[l] = span.width();
    
        var nb_lines = lines.length;
            ideal_line_width = 0;
    
        if(nb_lines == 1) {
            // If the line is "long", make it two
            if(span.width() >= h1.parent().width()/2) {
                ideal_line_width = h1.width()/2;
                nb_lines = 2;
            }
        }
        else {
            // Compute the average lines width (except for the last one)
            var sum = 0;
            for(l=0;l<(nb_lines-1);l++) {
                sum += lines[l];
            }
            var avg_width = sum/(nb_lines-1);
    
            // If last line is shorter than the average
            if(lines[nb_lines-1] < avg_width) {
                var gap = avg_width - lines[nb_lines-1];
    
                // Spread the gap among the lines
                gap /= nb_lines;
    
                if(gap > minimum_gap) {
                    ideal_line_width = avg_width - gap;
                }
            }
        }
    
        // Let's make the wanted adjustments
        if(ideal_line_width != 0) {
    
            // Determining which is the first word of each line, beginning at the end in order to get the shortest one first
            l = nb_lines-1;
            span.empty();
            for(i=words.length-1;i>=0;i--) {
                span.prepend(words[i] + ' ');
                if(span.width() > ideal_line_width) {
                    // If there's a new line, we cancel the last word
                    if(h1.height() > height) {
                        i++;
                    }
                    span.empty();
                    first_word[l] = i;
                    l--;
                }
            }
    
            // Applying the results
            span.remove();
            l = 1;
            for(i=0;i<words.length;i++) {
                h1.append(' ' + words[i]);
                if(first_word[l] == i+1) {
                    h1.append('<br>');
                    l++;
                }
            }
    
        }
        // Or just display the text
        else {
            span.remove();
            h1.text(text);
        }
    
    });
    

    您可以see it in action here。不幸的是,我仍然不喜欢#8 和#13。欢迎提示和改进。

    【讨论】:

      猜你喜欢
      • 2020-11-14
      • 2018-11-03
      • 1970-01-01
      • 2022-01-03
      • 2015-06-29
      • 1970-01-01
      • 1970-01-01
      • 2016-09-24
      • 2010-09-24
      相关资源
      最近更新 更多