Manage liste separator while the screen change size (media query) - html

I try to manage separators (like a "-") between each element of a list.
It's relatively simple when we only have one line, but I can't do it with more than one line.
When the site is displayed on a big screen I have:
Example center aligned
Listitem1 - listitem2 - listitem3 - ... - listitemX
The last item having no separator "-"
html
<p>
<a>listitem1</a>
<a>listitem2</a>
<a>listitem3</a>
<a>listitem4</a>
<a>listitem5</a>
<a>listitem6</a>
<a>listitem7</a>
...
<a>listitemX</a>
</p>
CSS
a:nth-child(n+2)::before {
content: " - "
}
This is relatively easy in CSS using :: before from the 2nd child...
But with media queries, when my screen shrinks and this same list spans multiple lines, I would like to remove the last "-" separator from each line.
Example center aligned
Listitem1 - listitem2 - listitem3 - listitem4 (without the separator here)
Listitem5 - listitem6 - listitem6 - listitem8 (without separator here either)
Listitem9 - etc ...
Does anyone have an idea?
Thank you in advance. Sebastian

There doesn’t seem to be a pure CSS solution, but you can use a bit of JS to set or unset a class based on whether an item is the first in a line.
Here I’m setting the text color to transparent rather than the content to "" because changing the content affects width, which then jumps around as it wraps/resizes.
a.firstInLine::before {
color: transparent;
}
The Javascript goes through the nodes and checks whether it’s lower on the page than the previous node. If it is (by more than a small margin of error), it sets the class firstInLine:
function calcY() {
document.querySelectorAll("p a").forEach((n, i, nodes) => {
if(i > 0) {
const thisY = n.getClientRects()[0].y;
const prevY = nodes[i - 1].getClientRects()[0].y;
if(thisY - prevY > 4) {
n.classList.add("firstInLine");
}
else {
n.classList.remove("firstInLine");
}
}
});
}
window.addEventListener("resize", calcY);
calcY();
I should add that there are a couple of other CSS things to set. We don’t want it to wrap, and in order for getClientRects to work right, it can’t be a purely inline element, so:
a {
white-space: nowrap;
display: inline-block;
}
CodePen

Related

Offset seems to be drasticly different per item i click

I have been working with creating a selection box around some cells, The selection box is absolute so it can reach everywhere it needs to, to create a click and drag box around some cells.
It seems that based on the mousedown event, the position of the box is set correctly for class hour but not for half-hour. While it is the same code, hour offset will return me the corrdinates of the item. relative to the doc, whereas the half-hour will return approx (0,6) which sets the top:left to the upper right corner.
Right now, my dom looks like this:
<div class="row">
<div class="cell hour">
<div class="half-hour"></div>
<div class="half-hour"></div>
</div>
</div>
and the CSS is:
.hour{
position:relative;
}
.half-hour{
display:inline-block;
float:left;
width: 50%;
height: 100%;
}
.row {
display: table-row;
}
.cell {
display: table-cell;
border: solid 1px black;
width: 20px;
text-align: center;
cursor: pointer;
}
From what it looks like is that the offset I am getting when selecting the half-hour is the offset to the parent hour and the hour i think is getting his relative to the page?
After looking at these, I was thinking that setting half-hour to: *position:relative;` might do the trick, but it didnt do anything. it is the same.
I am thinking i need to modify something. im just not sure what.
I will eventually be doing this same design for a class called: quarter-hour which will have 2 in each of the half-hour divs.
Edit based on the question below, I just have a simple: ` which is on the page, and then on mousedown it would:
1- Set Top:Left values based on mouse.target.offsetTop && mouse.target.offsetLeft respectively.
2- Set position absolute (though it should be already)
3- set dimensions, Height and Width accordingly.
Edit 2 I managed to recreate my issue with this fiddle https://jsfiddle.net/838vqboe/ I am currently giving 3 options in the DDL. Hour works as expected, but not HH or QH.
I ended up coming up with a solution which worked in Javascript, but when converting it to Dart, specifically with Polymer, the concepts behind shadowdom was alien to me. This I think is the issue I was having as it was determining a local root it was applying positions to while the mouse gave me positions in relation to the screen.
To resolve this, I noticed that something which extends PolymerElement has get getBoundingClientRect(), so i ended up doing something like the following in javascript:
var _mouseDown = function(e){
var selectedHtml = e.target;
var left = selectedHtml.getBoundingClientRect().left - getBoundingClientRect().left
var top = selectedHtml.getBoundingClientRect().top - getBoundingClientRect().top
_selectionDiv.css({left:left, top:top});
}
$selection.on("mousedown", _mouseDown);
and in Dart:
Function _mouseDown(MouseEvent mouse){
HtmlElement selectedElement =- mouse.target;
var left = selectedHtml.getBoundingClientRect().left - getBoundingClientRect().left;
var top = selectedHtml.getBoundingClientRect().top - getBoundingClientRect().top ;
_selectionDiv.style.top = "${top}px";
_selectionDiv.style.left = "${left}px";
}

how to auto-number each line in <p> element using CSS

I'm trying to auto-number each line that will be generated while displaying a
<p> element.
Perhaps using counters in CSS?
I'm looking for something along the lines of p:first-line, except for every line of the <p> element
something like:
p:each-line {
counter-increment line_num;
}
p:each-line:before {
counter(line_num) " " ACTUAL-LINE;
}
Can I do this with simple CSS code? How else could I achieve this?
I have an element called message, and I don't know in advance how many lines
of actual text will be formatted using that element style. If I change the
max-width for example and that forces more/fewer lines, I'd like this to automatically
number correctly the actual lines in the element.
/* set up the speech bubbles */
p.message {
position:relative;
padding:5px 10px;
border:2px solid rgb(74,77,82);
border:2px solid rgba(74,77,82,.5);
-moz-border-radius:10px;
-webkit-border-radius:10px;
border-radius:10px;
max-width: 70%;
}
Such a task is a little much for CSS alone to handle. It isn't too hard in javascript.
It sounded like a nice little distraction so I played around a bit in jsfiddle. Perhaps this will help even though it's not pure css and uses some jquery.
http://jsfiddle.net/rSFUB/2/
Notice that I wrapped the <p> text in a div and added a line number div within that absolutely positioned. The javascript is:
$(document).ready(function () {
$(".message").each(function () {
var self = $(this);
var numbering = self.find(".lineNumbering").first();
var messageText = self.find("p").first();
var lineHeight = numbering.text("...").height();
var lines = messageText.height() / lineHeight;
var lineNumberingHtml = "";
for(var i = 1; i <= lines; i++) {
lineNumberingHtml = "" + lineNumberingHtml + i + "<br />";
}
numbering.html(lineNumberingHtml);
});
});
I tested in IE10, Chrome, and Firefox. The only difference between this code in the various versions is the padding on the .lineNumber div in order for it to line up with the text. Note this assumes that the line number div text and the paragraph is the same line-height.

Placing words directly under or above other words

I wish to do the following within div tags:
The words will be coloured differently using spans.
I will be given some text in a text box and via JavaScript I will need to dynamically update to div to show something like the above.
What is the best way to do this?
Will it involve a monospaced font?
Will it involve writing "hidden" text?
I wish to do entire paragraphs in this manner.
This might seem weird but the research I'm doing requires me present certain words from a given text with multiple colours and I think this might be a nice way of conveying this information.
Updating the text in the text box will update the following variables, and in turn I will need to convert these two variables into something like the image above.
text = "I am under the text above me and there is lots more text to come./n I am even moving onto a new line since I have more text"
color_per_word_position = {0:green, 1: red, 2: cyan, 4: yellow, 5: red, ...}
You will have to use a monospaced font for this.*
I basically see two options: 1. use whitespace 2. margins.
Option 1
Your text will look like
I•am•under•the•text•above
••am•under•••••text•above
where • denotes a space character. Pretty straight-forward in terms of CSS, since you don't have to worry about the spacing. The browser does it all for you. Example: http://jsfiddle.net/PYXdr/
*well, it may be possible with any font, using a lot of JS, but I guess it's not worth it.
Option 2
Since you probably don't want whitespace in between your spans, you may prefer this:
I•am•under•the•text•above
am•under text•above
Now, the spacing needs to be taken care of manually. Each span should get a margin-left that pushes it to the desired position. But before we can do that, we need to know the width of one character (using JS, since CSS does not provide that). Okay, pretty easy:
var el = document.createElement('pre');
el.style.display = 'inline-block';
el.innerHTML = ' ';
document.body.appendChild(el);
var width = parseFloat(getComputedStyle(el).width);
document.body.removeChild(el);
Now let's go ahead and move the spans:
span1.style.marginLeft = (2 * width) + 'px';
span2.style.marginLeft = (5 * width) + 'px';
Example: http://jsfiddle.net/JC3Sc/
Putting it all together
Now here's a basic example of how this might work:
var text = "I am under the text above me and there is lots more text to come.\nI am even moving onto a new line since I have more text"
var highlightBorders = [[2, 3, 4, 6], [6, 7]]; // YOUR TASK: implement the logic to display the following lines
var color_per_word_position = {0:'lime', 1: 'red', 2: 'cyan', 3:'orange', 4: 'yellow', 5: 'red'}
/* generate CSS */
var style = document.createElement('style');
for (var i in color_per_word_position) {
style.innerHTML += '.hl' + i + '{background:' + color_per_word_position[i] + '}';
}
document.head.appendChild(style);
/* generating the text */
text = text.split('\n');
var pre = document.createElement('pre');
text.forEach(function (line, i) {
var div = document.createElement('div');
var words = line.split(' ');
var result = [];
highlightBorders[i].forEach(function (len, j) {
var span = document.createElement('span');
span.innerHTML = words.splice(0, len).join(' ');
span.className = 'hl' + j;
if (j) {
span.style.marginLeft = width + 'px' // YOUR TASK: implement the logic
}
div.appendChild(span);
});
pre.appendChild(div);
});
document.body.appendChild(pre);
This is not a complete solution, since a) I don't really see which parts exactly you want to highlight and b) I don't want to spoil all the fun. But you get the idea.
Example: http://jsfiddle.net/tNyqL/
Using padding this is possible but also have absolute control by assigning text to a selector such as "p" for the class: fiddle http://jsfiddle.net/3NDs3/1/
.one {
width:200px;
}
.one p {
font: normal 14px Futura, sans-serif;
text-align:left;
padding-left:130px;
}
.two {
width:200px;
}
.two p {
text-align:center;
font: normal 14px Futura, sans-serif;
}
.three {
width:200px
}
.three p {
text-align:left;
font: normal 14px Futura, sans-serif;
padding-left:35px;
}
<div class="one">
<p>above me</p>
</div>
<div class="two">
<p>i am under the text above me</p>
</div>
<div class="three">
<p>under</p>
</div>

show tinymce contents in a div with flexible though maximum height

When using an editor like tinymce, how could i limit the height of the text a user enters so it doesn't use more space on the webpage than i want it to?
There are 2 things that i want some advise on:
In the editor:
The user enters text in a tinymce editor, he could set a text to font-size say 80px which would use up more space than a normal letter. So it's not the amount of text that i care about it's the height of the total.
In the webpage:
I don't want to give them more than say 200px worth of text on the page. But if they enter just 1 line of text with a small font-size i don't want to show a 200px space. So the height has to be flexible but with a maximum.
I know this isn't exact science but the goal here is to prevent the user from messing up the page.
To solve a similar issue i wrote the following function (placed inside an own tinymce plugin). You will need to add a variable for the maximum case and maybe tweak it a bit, but i hope this code will put you into the right direction
// this function will adjust the editors iframe height to fit in the editors content perfectly
resizeIframe: function(editor) {
var frameid = frameid ? frameid :editor.id+'_ifr';
var currentfr=document.getElementById(frameid);
if (currentfr && !window.opera){
currentfr.style.display="block";
if (currentfr.contentDocument && currentfr.contentDocument.body.offsetHeight) { //ns6 syntax
currentfr.height = currentfr.contentDocument.body.offsetHeight + 26;
}
else if (currentfr.Document && currentfr.Document.body.scrollHeight) { //ie5+ syntax
currentfr.height = currentfr.Document.body.scrollHeight;
}
styles = currentfr.getAttribute('style').split(';');
for (var i=0; i<styles.length; i++) {
if ( styles[i].search('height:') ==1 ){
styles.splice(i,1);
break;
}
};
currentfr.setAttribute('style', styles.join(';'));
}
},

Is there any way to set a CSS min-width on an element that is floated?

I have this html:
<div id="subNav"></div>
<div id="feed"></div>
<div id="feedBar"></div>
I have floated all of these divs left. I set the width of #subNav and #feedBar, but on #feed I set its min-width . It takes the min-width even though the window is larger. Is there any way that with floating you can make the min-width work? I am trying to make a flexible layout on the page.
The following answer uses a JavaScript solution, in response to #Chromedude's comment (to the original question):
#David Is there any way to override this behavior? with javascript?
I'm sure there's a far more simple way of doing this (certainly with a JavaScript library), but this was the best I could come up with at this time of morning (in the UK):
var feed = document.getElementById('feed');
var width = document.width;
var feedBarWidth = document.getElementById('feedBar').clientWidth;
var subNavWidth = document.getElementById('subNav').clientWidth;
feed.setAttribute('style', 'width: ' + (width - (subNavWidth + feedBarWidth)) + 'px');
JS Fiddle demo.
Using jQuery (just as a suggestion as to the ease offered by a library):
var bodyWidth = $(document).width();
var subNavWidth = $('#subNav').width();
var feedBarWidth = $('#feedBar').width();
$('#feed').css('width', bodyWidth - (subNavWidth + feedBarWidth));
Use a grid system such as the one in Foundation 3. When placed on a div representing an element of the grid, min-width behaves just fine.
To get min-width to work without a grid, use a CSS rule that inserts an invisible pseudo-element with the desired minimum paragraph width.
p:before {
content: "";
width: 10em;
display: block;
overflow: hidden;
}
Further details are at the source where I learned this.