简体   繁体   English

如何选择最后一行文字的第一个单词? ( <h1> - <h6> , <p> 元素)

[英]How to select a first word of the last line of text? (<h1> - <h6>, <p> elements)

I need to add a little horizontal line under each of the h1 - h6 elements on the site I am building. 我需要在我正在构建的网站上的每个h1-h6元素下添加一条水平线。 I am currently adding an after element: 我目前正在添加一个after元素:

h1, h2, h3, h4, h5, h6 {
  text-transform: uppercase;
  color: #000;
  margin-top: 0;
  margin-bottom: 2rem;
  font-weight: 800;
  color: #333;
  display: inline-block;
  position: relative;
  text-rendering: optimizeLegibility;
  font-family: $altfont;
  position: relative;
  &:after {
    content: '';
    position: absolute;
    bottom:0;
    left:0;
    width: 60px;
    height: 4px;
    background-color: $yellow;
  }
}

I also have a small jQuery function to make sure that the after element is always 20px below the element: 我还有一个小的jQuery函数,以确保after元素总是低于元素20px:

$(function () {
    $('h1, h2, h3, h4, h5, h6').each(function () {

            x = parseInt($(this).css('font-size'));
            $(this).css('line-height', (x + 20) + 'px');

    });
});

this works if the h1 has text-align left - when the text wraps into 2 or more lines, the after element will show up under the first word of the last line. 如果h1左侧有文本对齐,则此方法有效 - 当文本换行为2行或更多行时,after元素将显示在最后一行的第一个单词下。

The problem is, if the text is center aligned, or right aligned, the after element will show up under the h1 element but not under the first word of the last line. 问题是,如果文本居中对齐或右对齐,则after元素将显示在h1元素下,但不会显示在最后一行的第一个单词下。 Is this something that can be done with JS/JQuery? 这是可以用JS / JQuery完成的吗?

Here is a pic of what happens. 这是一张发生了什么的照片。 In the second example, I would like the yellow line to show up under the word "Slice". 在第二个例子中,我希望黄色线显示在“Slice”一词下面。

在此输入图像描述

EDIT 编辑

This was a nice challenge! 这是一个很好的挑战!
It takes 4 loops to achieve what you ask. 它需要4个循环来实现您的要求。

  1. To add a span on each words. 在每个单词上添加span
  2. To find the offset of the span on the last line. 要查找最后一行的span偏移量。
  3. To remove spans on all lines except the last. 删除除最后一行之外的所有行的跨度。
  4. To remove spans on all words except the first. 删除除第一个以外的所有单词的跨度。

CodePen CodePen

See comments in code (I left all my debugging console.logs) . 请参阅代码中的注释(我留下了所有调试console.logs)

 $(function () { $('h1, h2, h3, h4, h5, h6').each(function () { x = parseInt($(this).css('font-size')); $(this).css('line-height', (x + 20) + 'px'); findWord($(this)); }); function findWord(el){ // Get the word array. var wordArr = el.html().split(" "); // Cycle words to add span on each words. for(i=0;i<wordArr.length;i++){ console.log(wordArr[i]); wordArr[i] = "<span class='underliner'>"+wordArr[i]+"</span>"; } // Update HTML. el.html(wordArr.join(" ")); // Find the offset of the last line. var biggestOffset=0; el.find(".underliner").each(function(){ console.log($(this).offset().top); if($(this).offset().top>biggestOffset){ biggestOffset=$(this).offset().top; } }); console.log("biggestOffset: "+biggestOffset); // Remove span on NOT the last line el.find(".underliner").each(function(){ if($(this).offset().top<biggestOffset){ $(this).replaceWith($(this).html()); } }); // On the last line, remove all spans except on the first word el.find(".underliner").not(":eq(0)").each(function(){ $(this).replaceWith($(this).html()); }); } }); 
 h1, h2, h3, h4, h5, h6 { text-transform: uppercase; color: #000; margin-top: 0; margin-bottom: 2rem; font-weight: 800; /*color: #333;*/ display: inline-block; position: relative; text-rendering: optimizeLegibility; font-family: $altfont; position: relative; text-align:center; /* ADDED */ /* REMOVED */ /*&:after { content: ''; position: absolute; bottom:0; left:0; width: 60px; height: 4px; background-color: &yellow; }*/ } .underliner{ text-decoration:underline; text-decoration-color: red } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <h1>This is a quite long H1 that will certainly wrap</h1> <h2>This is a quite long H2 that will certainly wrap</h2> <h3>This is a quite long H3 that will certainly wrap</h3> <h4>This is a quite long H4 that will certainly wrap</h4> <h5>This is a quite long H5 that will certainly wrap</h5> <h6>This is a quite long H6 that will certainly wrap</h6> 




First answer 第一个答案
(misread the question...) (误读了这个问题......)


Since you already use jQuery... 既然你已经使用了jQuery ......

You can add $(this).append($("<div class='smallBar'>").css({"top":x+10})) to the script... 您可以将$(this).append($("<div class='smallBar'>").css({"top":x+10}))到脚本中...
And use CSS to define smallBar the same way you did for the after pseudo element. 并使用CSS以与after伪元素相同的方式定义smallBar

CodePen CodePen

 $(function () { $('h1, h2, h3, h4, h5, h6').each(function () { x = parseInt($(this).css('font-size')); $(this).css('line-height', (x + 20) + 'px'); $(this).append($("<div class='smallBar'>").css({"top":x+10})) }); }); 
 h1, h2, h3, h4, h5, h6 { text-transform: uppercase; color: #000; margin-top: 0; margin-bottom: 2rem; font-weight: 800; /*color: #333;*/ display: inline-block; position: relative; text-rendering: optimizeLegibility; font-family: $altfont; position: relative; /*&:after { content: ''; position: absolute; bottom:0; left:0; width: 60px; height: 4px; background-color: &yellow; }*/ } .smallBar{ position: absolute; top:0; left:0; width: 60px; height: 4px; background-color: red; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <h1>This is a quite long H1 that will certainly wrap</h1> <h2>This is a quite long H2 that will certainly wrap</h2> <h3>This is a quite long H3 that will certainly wrap</h3> <h4>This is a quite long H4 that will certainly wrap</h4> <h5>This is a quite long H5 that will certainly wrap</h5> <h6>This is a quite long H6 that will certainly wrap</h6> 

My algorithm of finding and highlighting first word of last line: 我找到并突出显示最后一行第一个单词的算法:

  1. Iterate through elements. 迭代元素。
  2. Get element's text ( innerText ). 获取元素的文本( innerText )。
  3. Split text by whitespace (" ") sign. 按空格(“”)符号拆分文本。
  4. Remove all elements from block. 从块中删除所有元素。
  5. Add span s with words and whitespace text nodes (also save this span s to array). 添加span s的文字和空白文本节点(也保存这个span s到阵列)。
  6. Sort this array by span with the highest top and lowest left of span 's rectangle. 排序这个数组由span最高的top和最低leftspan的矩形。
  7. Add highlighting class to the top element of this array. 将突出显示类添加到此数组的顶部元素。

 highlightFirstWordOfLastLineForHeaders(); /* apply highlighting on window resize */ window.addEventListener("resize", highlightFirstWordOfLastLineForHeaders); /* Peforms highlightFirstWordOfLastLine call for every header element */ function highlightFirstWordOfLastLineForHeaders() { var elements = document.querySelectorAll("h1, h2, h3, h4, h5, h6"); for (var i = 0; i < elements.length; i++) { highlightFirstWordOfLastLine(elements[i]); } } /* Peforms highlighting for single element */ function highlightFirstWordOfLastLine(element) { var text = element.innerText.trim(); /* get words list */ var words = text.split(" "); /* removing all elements */ while (element.firstChild) { element.removeChild(element.firstChild); } var spanArray = []; /* add spans with words and whitespaces */ for (var i = 0; i < words.length; i++) { /* append span with word */ var span = document.createElement("span"); span.appendChild(document.createTextNode(words[i])); element.appendChild(span); /* append whitespace */ element.appendChild(document.createTextNode(" ")); /* save span element to array */ spanArray.push(span); } /* sorting by highest top and lowest left */ spanArray.sort(function(a, b) { var rectA = a.getBoundingClientRect(); var rectB = b.getBoundingClientRect(); var deltaTop = rectB.top - rectA.top; /* if differense is less then 1px */ if (Math.abs(deltaTop) < 1) { return rectA.left - rectB.left; } return deltaTop; }); /* appending highlighting to fist word of last line */ spanArray[0].classList.add("selected"); } 
 .selected { border-bottom: 2px solid yellow; } 
 <h1> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent ultrices porta nibh, eu semper massa ullamcorper et. </h1> <h2> Curabitur in venenatis sapien. Nullam cursus ante ac enim dapibus, a egestas tellus mollis. </h2> <h3> Aenean tincidunt ligula et egestas suscipit. Proin euismod felis leo, egestas porta purus porta vitae. Morbi ut pulvinar quam, eu accumsan eros. Duis tristique pretium imperdiet. Integer nunc odio, consectetur vel leo vel, posuere venenatis nunc. Vestibulum sit amet arcu sit amet tortor faucibus maximus in id massa. Praesent vulputate, tellus nec aliquam tempor, ipsum erat tincidunt est, sit amet cursus turpis dui ac ipsum. Duis nec odio in felis aliquet sagittis sit amet in leo. Suspendisse potenti. Curabitur vitae sagittis diam. Duis id lectus cursus purus ultricies sollicitudin. Phasellus a ex sit amet eros lacinia fringilla sit amet sit amet sem. Proin luctus ornare risus at volutpat. Aliquam eleifend porttitor nulla. Sed facilisis mattis felis ut sodales. </h3> <h4> Quisque quis ultricies arcu. Aliquam feugiat non ipsum quis malesuada. Suspendisse ullamcorper, eros ut maximus hendrerit, sem velit lobortis turpis, non tristique justo magna eu nulla. Vestibulum maximus auctor ipsum sit amet finibus. Etiam commodo iaculis sem, vitae tincidunt libero. Phasellus lacus quam, semper ut pulvinar sed, accumsan a arcu. Suspendisse nulla velit, rhoncus id porttitor at, dictum ac ante. Sed eleifend vitae quam eget pretium. </h4> <h5> Duis semper rhoncus ultrices. Aliquam id elit nec quam fringilla gravida ac sed nisi. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec lorem leo, rhoncus quis nulla eget, posuere pellentesque leo. Nam in nisi sit amet sem consequat sodales. Quisque leo urna, aliquet eu malesuada at, laoreet et lorem. Fusce est neque, fringilla id ex id, semper tincidunt mauris. Aliquam erat volutpat. Vestibulum sodales sodales tincidunt. Pellentesque elementum quis neque vel malesuada. Nulla non scelerisque enim, ut posuere tortor. Fusce vel neque tristique ipsum aliquet mattis at sed sapien. </h5> <h6> Praesent scelerisque magna libero, vitae commodo purus tincidunt in. Etiam placerat diam turpis, sit amet iaculis eros efficitur at. Sed porta, dui non condimentum vestibulum, libero enim cursus nibh, eu luctus ligula ante sed neque. Duis vestibulum lacus felis, at iaculis tellus malesuada at. Donec vehicula lacinia metus. Pellentesque non efficitur lectus. Etiam et consectetur massa. Proin et leo cursus, convallis diam sit amet, mattis arcu. Fusce posuere pharetra leo eget volutpat. Maecenas et posuere urna. Nullam a dolor eu ipsum placerat rhoncus. In cursus, mauris ut pulvinar pellentesque, diam orci facilisis ante, at sollicitudin libero turpis in libero. In maximus est eu nisl venenatis ultrices. </h6> 

You can also see how it works with window resizing via jsFiddle . 您还可以通过jsFiddle查看窗口大小调整的工作原理。

Although not tested this logic makes sense. 虽然未经测试,但这种逻辑很有意义

Write some JS that looks up the size of the h1, if the size of the h1 is greater than X which would be the size the h1 is with perhaps a little added on top for good measure. 写一些查看h1大小的JS,如果h1的大小大于X,那么h1的大小可能会稍微添加到顶部以获得良好的度量。

Then add styling to the h1 with and :after pseudo class that appears bottom:0 left:0. 然后使用和后面的伪类添加样式到h1:0左边:0。 this will however mean your text will have to be aligned left instead of center. 但这意味着您的文本必须左对齐而不是中心。

When the h1 wraps onto 2 lines the h1 size essentially doubles which will then cause the if statement to fire and add the styling to the text. 当h1包装到2行时,h1大小基本上加倍,然后将导致if语句触发并将样式添加到文本中。 This is the closest answer I have to perfect for you I apologise if you require the text to be central. 这是我必须为你完美答案的最接近的答案。如果你要求文本为中心,我道歉。

EDIT: Example code of above . 编辑:上面的示例代码

Now I can't say this will work but here is some basic code around based on the previously explained method. 现在我不能说这会起作用,但这里有一些基于前面解释过的方法的基本代码。 Im not amazing with javascript so you will more than likely need to build on. 我对javascript并不惊讶,所以你很可能需要继续构建。 But at least this gives you a starting point I hope... 但至少这给了你一个起点我希望...

JS JS

$(document).ready(function() {
var h1Height = document.getElementsByTagName("h1").offsetHeight;

function firstH1Wrap() {
    if (h1Height < /*line-height+5px*/){
        document.getElementsByTagName("h1").addClass('hide-line');
    } else {
        document.getElementsByTagName("h1").removeClass('hide-line');
    }
}
});

$(window).resize(firstH1Wrap).trigger('resize')

CSS CSS

h1, h2, h3, h4, h5, h6 {
    text-transform: uppercase;
    color: #000;
    margin-top: 0;
    margin-bottom: 2rem;
    font-weight: 800;
    color: #333;
    display: inline-block;
    position: relative;
    text-align: left;
    text-rendering: optimizeLegibility;
    font-family: $altfont;
    position: relative;
}

h1:after, h2:after, h3:after, h4:after, h5:after, h6:after {
    content: '';
    position: absolute;
    bottom:0;
    left:0;
    width: 60px;
    height: 4px;
    background-color: $yellow;
    display: block;
}

h1.hide-line:after, h2.hide-line:after, h3.hide-line:after, h4.hide-line:after, h5.hide-line:after, h6.hide-line:after {
    display: none;
}

If you was to set the line height of all the Headings 1-6 the same you could run the same function for all of them as they have the same sizing, if you don't then you'll need to declare a new variable for each of the headings and build it into the function or make new ones. 如果要将所有标题1-6的行高设置为相同,则可以为所有标题设置相同的函数,因为它们具有相同的大小,如果不这样,则需要声明一个新的变量每个标题并将其构建到函数中或创建新函数。

This is not possible to fix based on the way you wrote the code. 根据您编写代码的方式,无法修复此问题。 But I think I have a solution if you are willing to change a few things. 但是如果你愿意改变一些事情,我想我有一个解决方案。 My method will only work if you know the font-size property of the element you are addressing. 只有在知道要寻址的元素的font-size属性时,我的方法才有效。

UPDATED CSS 更新的CSS

h1 {
  font-size: 24px; /* ADDED */
  text-transform: uppercase;
  color: #000;
  margin-top: 0;
  margin-bottom: 2rem;
  font-weight: 800;
  color: #333;
  display: inline-block;
  position: relative;
  text-rendering: optimizeLegibility;
  font-family: $altfont;
  position: relative;

  &:after {
      content: '';
      position: absolute;
      top: 24px; /* FONT SIZE = DISTANCE */
      left:0;
      width: 60px;
      height: 4px;
      background-color: $yellow;
  }
}

This should work however it is untested. 这应该有效,但是未经测试。

It works by knowing the font-size and then using that value as a top margin. 它的工作原理是知道font-size ,然后使用该值作为上边距。 So it will always be in the same location regardless in the text alignment changes. 因此,无论文本对齐方式如何变化,它都将始终位于同一位置。

EDIT: I now understand what you would like to accomplish. 编辑:我现在明白你想要完成什么。

This is very difficult to do because the line could be in many different locations. 这很难做到,因为这条线可能位于许多不同的位置。 The only solution I can think of from the top of my head is: 我能想到的唯一解决方案是:

Media Queries 媒体查询

You would need to create a breakpoint anytime and everytime the text wraps or the first word of the last line moves. 您需要随时和每次文本换行或最后一行的第一个单词移动时创建断点。

var text = $(this:last).text().trim().split(" ");
var last = text.pop();
$( this:last).html(text.join(" ") + (text.length > 0 ? " <span class='lastWord'>" + last + "</span>" : last));
};

And in the CSS add this 并在CSS中添加此内容

 .lastWord{text-decoration:underline;}

just put a 刚放一个

top:'whatever is line-height + 20px'

to the :after element (and remove bottom) 到:after元素(并删除底部)

edit:nm i missed the ' I would like the yellow line to show up under the word "Slice".' 编辑:nm我错过了'我希望黄色线出现在“Slice”这个词下面。 part 部分

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM