How to truncate text with JS/React, and replace the end of the line with a custom SVG icon instead of the CSS default ellipsis (...)?
Example situation:
.container {
width: 150px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
background: #90e4ff;
margin-bottom: 8px;
padding: 2px;
}
<div class="container">
The text here fits.
</div>
<div class="container">
This text here is way too long and certainly doesn't fit.
</div>
The output in the second div with the too long text is: This text here is way...
But the desired output would be: This text here is way<CustomIcon>
Thank you for the good question:)
By CSS only you cannot use an icon. I tried to think out a solution with JS. As you can see if the background of the SVG is transparent, the text below is visible. So better to use white background to cover the text.
Another important thing is that you need to use spans because divs have default width of 100%.
const containers = document.querySelectorAll('.container');
for (let i=0; i< containers.length; i++) {
if (containers[i].offsetWidth > 150) {
containers[i].style.width = "150px";
containers[i].style.setProperty('--height', '20px');
containers[i].style.setProperty('--width', '20px');
}
}
.container {
overflow: hidden;
white-space: nowrap;
text-overflow: clip;
background: #90e4ff;
position: relative;
display: inline-block;
}
.container:after {
content: "";
width: var(--width, 0);
height: var(--height, 0);
background: url("https://www.svgrepo.com/show/5044/heart.svg") 0 0 no-repeat;
position: absolute;
top: 0;
right: 0;
display: inline-block;
background-size: contain;
}
<span class="container"> The text here.</span>
<span class="container"> This text here is way too long and certainly doesn't fit.</span>
Related
The project:
I made a 3 items slider just using CSS and JS. I'm trying to adjust the proportion of one item to make sliding based on this proportion.
The problem:
the proportion isn't fixed and there is a slight space from the left side of all items and between items themselves. It seems they have borders that take a tiny space. and that space also affects sliding itself. I don't know if it's a CSS or JS problem!
Source Code on Codepen
HTML
<div id="slider">
<div class="SlideContainer">
<div class="img">
<img src="https://www.nicepng.com/png/detail/11-112605_punk-cat-berkley-cats-illustrations.png">
</div>
<h1 style="text-align:center;">1</h1>
</div>
<div class="SlideContainer">
<div class="img">
<img src="https://i.pinimg.com/736x/84/78/b9/8478b93283dc6eac074d437097a9fe74.jpg">
</div>
<h1 style="text-align:center;">2</h1>
</div>
...... etc
</div>
CSS
#slider {
height: 500px;
margin: 0;
padding: 0 .5%;
overflow: hidden;
white-space: nowrap;
scroll-behavior: smooth;
}
.SlideContainer{
vertical-align: top;
background-color: purple;
color: white;
height: 99% ;
margin: .5% 0;
width: 33%;
display: inline-block;
}
.img {
overflow: hidden;
max-width:200px;
max-height:200px;
border-radius: 50%;
display: block;
margin: 10px auto 0 auto;
text-align: center;
}
.img img{
height: 200px;
width: 200px;
}
JS
var Container = document.getElementById("slider");
var unitWidth = (Container.offsetWidth/3);
var slidesNo = (document.getElementsByClassName("SlideContainer").length - 2);
var i = 0;
var positionInfo = Container.getBoundingClientRect();
var height = positionInfo.height;
var width = (positionInfo.width/3);
function SlideLoop(){
var interval = setInterval(function(){
Container.scrollTo((unitWidth * i), 0);
//Container.scrollBy(unitWidth, 0);
i++;
if(i == slidesNo) {
i = 0;
clearInterval(interval);SlideLoop();
}
}, 1500);
};
SlideLoop();
Your problem is with using white-space: nowrap; in the slider and display: inline-block; in the slider items.
Using such methods to display items is not recommended because it would cause strange unexpected behavior. I suggest you learn flexbox. This is a great and easy guide that will help you.
as for your problem, change those css elements like this and it should work propely:
#slider {
height: 500px;
margin: 0;
padding: 0 .5%;
overflow: hidden;
scroll-behavior: smooth;
display: flex; /* displays items horizontally */
}
.SlideContainer{
vertical-align: top;
background-color: purple;
color: white;
height: 99% ;
margin: .5% 0;
min-width:33%; /* force the minimum width of items */
}
I'm new in coding, so please be nice with me :)
I'm trying to show the hidden text on mouseover.
I would like a transion from right to left, but only where there is actually some hidden/ellipsised text ( I cannot know how long is it)
I'have something like this:
<div class="card">
<div class="text-box">
<h1> /*injected text*/ </h1>
</div>
</div>
css :
.text-box {
background-color: blue;
color:white;
}
h1 {
text-overflow: ellipsis;
overflow: hidden;
#include transition(left 4s linear);
overflow-x: hidden;
position: relative;
right: 0px;
}
.card:hover h1, .card:active h1 {
right:100px;
overflow: visible;
}
I need something similiar to the third, but only for ellipsised text
https://codepen.io/yurigor/pen/mAPkWP
thanks
Here's the code you only need from that codepen snippet
html
<div class="marquee bluebox">
<span><span>Hover over or touch me to see animated scrolling of this string. Fancy but buggy. May be still can be improved.</span></span>
</div>
css
.bluebox, .stuff {
box-sizing: border-box;
padding: 5px;
width: 300px;
border: 1px blue solid;
background-color: rgba(0, 0, 255, 0.4);
margin-bottom: 5px;
float: left;
}
.marquee {
white-space: nowrap;
overflow: hidden;
}
.marquee span {
display: inline-block;
width: 100%;
}
.marquee span span {
transition: left 4s linear;
position: relative;
overflow: hidden;
text-overflow: ellipsis;
left: 0px;
}
.marquee:active span, .marquee:hover span {
width: auto;
}
.marquee:active span span, .marquee:hover span span {
left: calc(300px - 15px - 100%);
}
here's a demo
https://jsbin.com/dukukid/edit?html,css,output
the css code with a minor modification to avoid transition when the text going back to initial position. although i highly recommend you learn SASS because it makes the code snippet shorter as you can see in your link.
/*this function take a DOM element as an input, test if this element have an overflow
and then apply ellipsis and transition to it if its the case*/
function transitionEllipsised(element, textToAdd){
/*get the jQuery collection of this element to use jQuery innerHeight and innerWidth
methods on it and add the text to it*/
var $element = $(element).text(textToAdd);
//if the text did overflow in the width or the height of the container apply ellipsis transition
if (element.scrollHeight > $element.innerHeight()
|| element.scrollWidth > $element.innerWidth()) {
var innerHtml = $element.html();
//add marquee class to the element it will hide the overflow
$element.addClass("marquee")
//wrap the element in the two spans that will create the transition effect
.html(`<span><span>${innerHtml}</span></span>`);
}
}
//this is an example to use the function transitionEllipsised
/*when user click on the button the text on the input will be added to the h1 element
and apply transition only if text overflow*/
$("button.add-text").click(function(){
var headerExample = document.querySelector("h1.header-example");
//get the text of the user input
var textToAdd = $("input.text-to-add").val();
transitionEllipsised(headerExample, textToAdd);
});
/*hide overflow*/
.marquee{
white-space:nowrap;
overflow: hidden;
}
/*the css that you need to do the transition effect*/
.marquee span{
display: inline-block;
width: 100%;
}
.marquee span span{
position: relative;
overflow: hidden;
text-overflow: ellipsis;
left: 0px;
}
.marquee:active span,
.marquee:hover span{
width: auto;
}
.marquee:active span span,
.marquee:hover span span{
transition: left 4s linear;
left: calc(300px - 15px - 100%);
}
/*header of the example*/
h1.header-example{
/*important to fix the width and height of the container. if the text is longer the 300px there will be an overflow*/
width: 300px;
height: 40px;
border: red solid 1px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<!-- this is an example to use the function transitionEllipsised -->
<p>add some text using the input. if the text is longer then the container there will be transition effect to show the overflow</p>
<input type="text" class="text-to-add"><button class="add-text">add text</button>
<h1 class="header-example"></h1>
I have pictures in a horizontal scroll and I want to be able to hover over each image, and when I do, I want the picture to be slightly "grayed out" with text over it.
I can't for the life of me figure out how to do it.
I made this fiddle to show what my scroll bar looks like.
https://jsfiddle.net/burgoyne/u1zdn80p/1/
#scroll {
height: 25%;
overflow-x: scroll;
white-space: nowrap;
width: 50%;
}
#scroll img {
height: 100%;
vertical-align: top; /* this prevents vertical whitespace */
}
Can someone point me in the right direction here? I have been trying different things with CSS to gray it out and add text, with no luck.
Thanks!
You have to specify what you want in a CSS img:hover rule, like this:
html, body {
height: 100%;
margin: 0;
padding: 0;
width: 100%;
}
#scroll {
height: 25%;
overflow-x: scroll;
white-space: nowrap;
width: 50%;
}
#scroll img {
height: 100%;
vertical-align: top; /* this prevents vertical whitespace */
}
#scroll img:hover {
opacity: .5;
}
<div id="scroll">
<a href="http://www.google.ca"><img src="http://www.fotoviva.co.uk/image/cache/data/prods/doug-blue-lake-500x500.jpg" /><!--
--><a href="http://www.google.ca"><img src="http://wannasmile.com/wp-content/uploads/2009/09/c76c_Gordon-McBryde-Field-Sunset-500x500.jpg" /><!--
--><a href="http://www.google.ca"><img src="http://creativefan.com/important/cf/2012/10/patio-garden-ideas/nice-patio-gardeen.jpg" /><!--
--><a href="http://www.google.ca"><img src="http://globotours.net/wp-content/uploads/2015/05/Desert-Safari-Dubai-500x500.jpg" />
</div>
About the gray color over the image, you can just add opacity to the image on hover ("opacity: 0.5") and, if you want, some transition between the event and the "grayness" with "transition: 0.5s" or so.
About the problem with the text overlay, I think you should visit this answer: Text on image mouseover?
You can place text inside with class named
<span class="text-content"><span>Some text here</span></span>
and then u can use css to place text on the image, something like ...
span.text-content
{
background: rgba(0,0,0,0.5);
color: white;
cursor: pointer;
display: table;
height: 150px;
left: 0;
position: absolute;
top: 0;
width: 150px;
}
span.text-content span
{
display: table-cell;
text-align: center;
vertical-align: middle;
}
I hope this helps.
I am trying to put together a page that will have a horizontally scrolling pane on it - here is an example of the layout I am looking to get:
The content is dynamically added and has varying dimensions. .
Here's some HTML:
<div class="container">
<div class="inner">
<div></div>
<div></div>
<div></div>
</div>
</div>
Base CSS:
.container {
width: 100%;
height: 100%;
}
.container .inner {
position: relative
}
.container .inner > div {
float: left;
}
Currently the only way I can get it working is by setting an explicit width for .inner. Otherwise, closest I've come is this answer, but it's still pretty far off my desired effect. Is it possible to achieve what I'm looking for with HTML/CSS alone or will I have to resort to javascript?
Is this what you expected? http://jsfiddle.net/GE5Hf/4/
Just use white-space: nowrap together with the inline-block and vertical-align: top. You don't need your .inner div to achieve the desired effect - just use one container with overflow-x: auto:
<div class="container">
<div id="i1"></div>
<div id="i2"></div>
<div id="i3"></div>
</div>
CSS
.container {
width: 100%;
height: 100%;
overflow-x: auto;
white-space: nowrap;
}
.container > div {
display:inline-block;
vertical-align: top;
}
Note: it is better to use overflow-x: auto than scroll just in case the scrollbar is not needed.
EDIT: We were speculating whether you actually need that .inner div. If you need it, you can just add it back with no special style required: http://jsfiddle.net/GE5Hf/5/
EDIT 2: To have the .inner div the width as its children, simply give it display:inline-block: http://jsfiddle.net/GE5Hf/8/
EDIT 3: Tried what you suggested in your last deleted comment, i.e. remove the fixed width of the child. This was really tricky, I had to wrap each child element to special div with display: table-cell and the inner div gets dislay: table-row: http://jsfiddle.net/GE5Hf/12/
This can be done using CSS only.
Here's a jsFiddle.
The solution is to set position: relative; on .container, which creates a new stacking context inside the .container, setting position: absolute; and white-space: nowrap; on .inner ensures that .inner's content div's will not wrap to the next line and that .inner will grow with its content, adding display: inline-block; and vertical-align: top; on the .inner > div's ensures that they are treated as inline elements and stick to the top of their containing element.
I believe this is what you are after, I have checked on the latest versions of IE, Chrome, Firefox and Safari and it works fine on all of them, I have no reason to believe that it won't work on older versions.
HTML
<div class="container">
<div class="inner">
<div></div>
<div></div>
<div></div>
</div>
</div>
CSS
.container {
position: relative;
width: 220px;
height: 400px;
overflow-x: scroll;
}
.container .inner {
position: absolute;
white-space: nowrap;
background-color: #FFCCFF;
}
.container .inner > div {
vertical-align: top;
display: inline-block;
margin: 10px;
}
Is position: relative mandatory ?
.container .inner {
position: fixed;
overflow: hidden;
}
demo
#styke You can do that with display:inline-block(and some font-size on .inner > div) and font-size:0 to div.inner.Provided fiddle here: http://jsfiddle.net/zepva/4/ , ignore the colors, i used them only for demonstrationfont-size:0 will remove the gaps between the element using display:inline-block so when you will get the total width of the div.inner, that will be the sum of children divs
Take a look at this, no script was necessary:
.container {
width: 300px;
height: 100%;
background-color: silver;
}
.container .inner {
white-space:nowrap;
padding: 10px;
overflow-x: scroll;
background-color: gray;
}
.container .inner > div {
display: inline-block;
vertical-align:top;
background-color: red;
border: 1px solid black;
}
Demo: http://jsfiddle.net/er144/4FLWK/
display:inline-block, with vertical-align:top , that way your text wont fall at the bottom of the container.
.container .inner > div {
display:inline-block;
vertical-align:top;
}
Check this jsFiddle.
The orange bar is serving as a progress bar where the value under the circle is how high the progress bar should be.
Any idea why the overflow:hidden; is beeing disregarded and how do one solve this problem? Oblviously nothing should go outside the circle.
Also is there a better solution for this?
Modified your fiddle a little bit. Here is the link
Modifications:
Changed .outerContainer css to display:block from display:table and addedmargin-top:30px to p css
Check if this works for you.
position: absolute and overflow: hidden don't appear to be playing nicely with display: table/table-cell. Removing the table stuff you had in there to vertically center the text fixes the problem. In Firefox, at least.
I think it's the browser thing...
This is the CSS3 version...
.progressBar {
display: block;
width: 100%;
height: 0;
position: absolute;
bottom: 0;
left: 0;
background: #ec6730;
transition: height 1s;
}
.innerContainer:hover > .progressBar {
height: 300px;
}
http://jsfiddle.net/ZyhgT/2/
It no longer flashing 'cause browser handle the job (not js loop animation...). But still it shows the edge on animation finish!!! This could be the browser things... Could be a bug...
This is not related to jQuery or any javascript. In fact, if you delete all your javascript and manipulate the height of your .progressBar using css on li:hover, you will notice the bug anyway.
It appears to be a browser issue as reported on: https://code.google.com/p/chromium/issues/detail?id=157218
As a workaround try adding an imperceptible css transform to the mask element:
.outerContainer {
-webkit-transform: rotate(0.000001deg);
}
You just need to change your .outerContainer class and it works just fine!
.outerContainer {
position: relative;
display: block;
height: 96px;
width: 96px;
overflow: hidden;
background: #fff;
border: 2px solid #fff;
-webkit-border-radius: 50px;
border-radius: 50px;
}
Put the level class inside the outerContainer div and style the span inside the level class to be relatively positioned. In the JavaScript, to calculate the level, divide by 10 instead of 100 for the perfect circular hover effect.
Here is a fiddle.
HTML
<div class="outerContainer">
<div class="innerContainer">
<p>Circle 3</p>
<span class="progressBar"></span>
</div>
<div class="level"><span>75</span>
</div>
</div>
CSS
body {
background: blue;
}
#circles {
text-align: center;
margin: 100px 0;
}
li {
display: inline-block;
margin: 0 10px;
position: relative;
}
.outerContainer {
position: relative;
display: block;
height: 96px;
width: 96px;
overflow: hidden;
background: #fff;
border: 2px solid #fff;
-webkit-border-radius: 50px;
border-radius: 50px;
}
.innerContainer {
display: table-cell;
vertical-align: middle;
width: 100%;
margin: 0 auto;
text-align: center;
}
p {
color: #000;
width: 96px;
position: relative;
z-index: 2;
}
.progressBar {
display: block;
width: 100%;
height: 0;
position: absolute;
bottom: 0;
left: 0;
background: #ec6730;
}
.level span{
position:relative;
}
JS
$(function() {
$("#circles li").hover(function(){
var thisElement = $(this);
var level = $(this).find(".level").text();
var elementHeight = $(this).find(".outerContainer").height();
level = (level/10)*elementHeight;
$(thisElement).find(".progressBar").stop().animate({
height: level
}, 300);
}, function() {
var thisElement = $(this);
$(".progressBar").stop().animate({
height: 0
}, 300);
});
});
display: table doesn't work that good with CSS positioning;
you should avoid using that, and find some other way to vertically center your labels.
If your circles have a known height, like your code seems to indicate (height:96px ecc), then just use a fixed top position for an absolutely positioned <p> element:
http://jsfiddle.net/ZyhgT/5/
Note that you don't even need jQuery for this, it is all achievable with just CSS3 (unless you are targeting old browsers)