CSS - Have Image Move With Centered Text-Align Input Text - html

I have an text input with the following HTML:
<span>
✍
</span>
<input type="text">
and the corresponding CSS:
input{
text-align: center;
border: none;
outline: none;
background-color: transparent;
}
The input element should blend seamlessly into its background with only the HTML icon indicating that it is indeed an input. The HTML icon will remain in a static position with the current mark-up as new text is added into the input.
Is there anyway to have my HTML icon start right to the left of the first letter and have it gradually move toward the left as the left boundary of the text string pushes in the same direction?
Fiddle Example

If you're ok with contenteditable you could try this:
span{
display: inline-block;
position: relative;
left: 50%;
transform: translateX(-50%);
}
span::before {
content: '\270D';
}
<span contenteditable='true'></span>

A possible but imperfect (needs lots of work) idea using jquery.
fiddle
$('input').bind('keypress', function(e) {
var tester = $(this).val().length;
var code = e.keyCode || e.which;
var currentWidth = $('input').css('width').slice(0, -2);
var currentWidthParsed = parseInt(currentWidth, 10);
if(code == 8) {
var newWidth = (currentWidthParsed - 8) + 'px'
$('input').css('width', newWidth);
} else {
var newWidth = (currentWidthParsed + 8) + 'px'
$('input').css('width', newWidth);
}
});
body {
text-align: center;
}
input{
text-align: left;
border: none;
outline: none;
background-color: transparent;
width: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<span>
✍
</span>
<input type="text">

As far as I know you can't have dynamic width of inputs with something like width: auto. In that case you could have a wrapper with fixed with and a text-align right.
So I would say the only possibility is to have that icon inside the value of the input (if it may exist as UTF-8 icon) and then strip it out when processing the value. But of course this would seem dirty.

Related

CSS-Add round status button on top of another

I am new to css. How can I add a status button which changes color depending on chat availability on top of another button?
You can use the position property.
See an example code here.
Some resources:
https://www.w3schools.com/css/css_positioning.asp
https://developer.mozilla.org/en-US/docs/Web/CSS/position
From the picture i can tell you don't have to use 2 html elements on top of each other, but you can use css properties like border and background-color to achieve exactly as the button in your picture.
I posted how in the code below with even a little bit of javascript to toogle the button status (not needed for styling, so if you don't know any javascript yet, you can skip that part).
let isOpen = false;
const btn = document.querySelector("#btn");
const dot = document.querySelector(".dot");
const txt = document.querySelector("#text");
btn.addEventListener("click", () => {
if (isOpen) {
dot.style.backgroundColor = "red";
txt.innerHTML = "The chat is now closed";
} else {
dot.style.backgroundColor = "green";
txt.innerHTML = "The chat is now open";
}
isOpen = !isOpen;
});
.dot {
height: 25px;
width: 25px;
background-color: red;
border-radius: 50%;
display: inline-block;
border: 5px solid gray;
}
#wrapper {
border: 1px solid black;
text-align: center;
padding: 10px;
}
#btn {
margin-top: 10px;
}
<div id="wrapper">
<span class="dot"></span>
<p id="text">The chat is now closed</p>
</div>
<button id="btn">Toogle</button>

How can I slide out a line on the left and right side of text on mouse hover

Essentially, I'm looking to animate a line on the left and right side of text that will increase its width to the end of the display when I hover over the text.
Perhaps this will help...
without hovering:
SOME TEXT
on hover:
----------------------------SOME TEXT--------------------------------------------------------------------------------------
I'd like these lines to animate outward to the end on the parent. I've tried using the pseudo elements but had no luck. Some help would be greatly appreciated.
Here's how I'd do it. Feel free to play with animation duration and timing function:
.separator {
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
.separator:before, .separator:after {
content: '';
flex-grow:0;
height: 1px;
background-color: currentColor;
transition: flex-grow .6s cubic-bezier(.4,0,.2,1);
margin: 0 .5rem;
}
.separator:hover:before, .separator:hover:after {
flex-grow: 1;
}
<div class="separator">SOME TEXT</div>
<div style="width: 50%; margin-top: 60px;border: 1px solid red; color: blue; padding: 3rem 0;">
<div class="separator">TEST</div>
Here's a JavaScript solution. Adds - to either side until it reaches the end of the line, and it removes the dashes when the mouse moves away.
To prevent the overflow, you just have to track the clientHeight and stop adding dashes as soon as the height increases.
var div = document.getElementsByClassName('test')[0];
var origText = div.innerText;
var origHeight = div.clientHeight;
var tooLong = false;
var addTxtInt;
div.addEventListener('mouseover', function() {
addTxtInt = setInterval(function() {
if (tooLong)
return;
if (div.clientHeight > origHeight) {
div.innerText = div.innerText.substring(1, div.innerText.length - 1);
tooLong = true;
return;
}
div.innerText = "-" + div.innerText + "-";
if (div.clientHeight > origHeight) {
div.innerText = div.innerText.substring(1, div.innerText.length - 1);
tooLong = true;
return;
}
}, 80);
});
div.addEventListener('mouseleave', function() {
clearInterval(addTxtInt);
div.innerText = origText;
tooLong = false;
});
.test {
display: block;
overflow: hidden;
text-align: center;
}
<div class='test'>SOME TEXT</div>

Make font smaller if there is big text

I have div and within that div text is displayed
<div class="td">
<div class="title main-color">test text</div>
</div>
but if there is big text it goes outside of div. I want to make that if there's big text font to become smaller. How can I achieve that?
JSFIDDLE is here
P.S. I don't want div to grow in height
Demo
https://jsfiddle.net/qjgjg2vh/
Html
<div class="td">
<div class="title main-color">test text</div>
</div>
<div class="td">
<div class="title main-color">test text is bigger now and goes outside of div and dont appears</div>
</div>
CSS
.main-color {
opacity: 0.6;
background: #ffffff;
}
.title {
height: 100%;
width: 470px;
border-radius: 20px;
float: left;
text-align: center;
line-height: 100px;
font-size: 26px;
overflow: hidden;
}
.td {
margin: 60px 0;
height: 100px;
width: 100%;
}
JQUERY
Your original code was getting the character count for ALL paragraphs that matched '.question p'. e.g. If you had two paragraphs, one with ten characters, the other with twenty characters, your JS would run once with a total of thirty, rather than processing each paragraph in turn.
$(function($){
$(".title.main-color").each(function () {
var numChars = $(this).text().length;
if ((numChars >= 1) && (numChars < 20)) {
$(this).css("font-size", "2.2em");
}
else if ((numChars >= 20) && (numChars < 60)) {
$(this).css("font-size", "1.8em");
}
else if ((numChars >= 60) && (numChars < 100)) {
$(this).css("font-size", "1em");
}
else if ((numChars >= 100) && (numChars < 140)) {
$(this).css("font-size", "0.9em");
}
else {
$(this).css("font-size", "0.8em");
}
});
});
You can use javaScript and make the font size smaller and smaller till the time the height of child element with the text fits the height of parent element. I also added visibility:hidden for the text and visibility:visible after fontSize decrease in order to get rid of flashing effect. Remember to put the text into extra element, eg. span. Change the text length to see the effect.
var samp = document.getElementById('samp');
fitFont(samp);
function fitFont(elem){
var child = elem.children[0];
var getFontSize = parseFloat(window.getComputedStyle(child).getPropertyValue('font-size'));
while(child.offsetHeight>elem.clientHeight){
getFontSize -= .1;
child.style.fontSize = getFontSize + 'px';
}
child.style.visibility = 'visible';
}
#samp {
background-color:white;
width:300px;
height:100px;
border:solid 2px #33aaff;
}
#samp span {
display: inline-block;
visibility:hidden;
font-size:50px;
}
<div id="samp">
<span>test text is bigger now and goes outside of div and dont appears test text is bigger now and goes outside of div and dont appears test text is bigger now and goes outside of div and dont appears
</span>
</div>
Of course you could aim for a javascript solution count the letters/words and adjust the font-size accordingly.
$(function() {
var $title= $(".title");
var $numWords = $title.text().split(" ").length;
if (($numWords >= 1) && ($numWords < 10)) {
$quote.css("font-size", "36px");
}
else if (($numWords >= 10) && ($numWords < 20)) {
$title.css("font-size", "32px");
}
else if (($numWords >= 20) && ($numWords < 30)) {
$title.css("font-size", "28px");
}
else if (($numWords >= 30) && ($numWords < 40)) {
$title.css("font-size", "24px");
}
else {
$title.css("font-size", "20px");
}
});
But if you want to use something without Javascript you could do a couple of things.
Unfortunately changing the font-size based on text-length is not possible with css.
Alternatives:
use a horizontal scrollbar (overfloy-x: scroll;)
make the box larger, (any dimension) https://jsfiddle.net/zjaq98Ln/10/
(show the overflow of text) probably not ideal
use text-overflow: https://jsfiddle.net/zjaq98Ln/9/
Try this
.main-color {
opacity: 0.6;
background: #ffffff;
}
.title {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
width: 470px;
border-radius: 20px;
float: left;
line-height: 30px;
font-size: 26px;
}
.td {
margin: 60px 0;
height: 100px;
width: 100%;
}
<div class="td">
<div class="title main-color">test text</div>
</div>
<div class="td">
<div class="title main-color">test text is bigger now, goes outside of div and doesn't appear</div>
</div>
Live demo here: https://jsfiddle.net/grinmax_/zjaq98Ln/11/

Hover over words in a text

What would be the best way to display a hover popup with a 20-30 words definition of each word in a foreign-language text?
Right now I am using an iframe:
<span class="tooltip">foreign-language-verb
<span class="tooltiptext">
2nd pers. sing. past tense, active mood.
<iframe class="tooltip" src="general_dictionary_definition_of_the_verb.html"></iframe>
</span>
</span>
It works but the page is then very slow to load and there seems to be a limit to the number of possible iframe's: they don't display anymore if the text is too long.
Any other solution, using javascript to load the text or something?
Thanks.
EDIT:
Following up on Richard P's remark: does that mean replacing iframe with javascript loading by hand, does that make sense, is that best practices? Would that be faster than the iframe's which are very slow to load?
Taking Javascript - read local text file into account:
<script type="text/javascript">
function loadDictionaryDefinitions()
{
var elements = document.getElementsByClassName("DictionaryDefinition");
for (var i = 0; i < elements.length; i++)
elements[i].innerHTML = readTextFile("file://" + elements[i].getAttribute("filename_of_dic_definition"));
}
function readTextFile(file)
{
var rawFile = new XMLHttpRequest();
rawFile.open("GET", file, false);
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState === 4)
{
if(rawFile.status === 200 || rawFile.status == 0)
{
var allText = rawFile.responseText;
alert(allText);
}
}
}
rawFile.send(null);
}
</script>
and add:
<body onload="loadDictionaryDefinitions()">
what about css hover ? Try this one:
https://jsfiddle.net/maky/0h0ekhj6/
/* Tooltip container */
.tooltip {
position: relative;
display: inline-block;
border-bottom: 1px dotted black;
/* If you want dots under the hoverable text */
}
/* Tooltip text */
.tooltip .tooltiptext {
visibility: hidden;
width: 120px;
background-color: black;
color: #fff;
text-align: center;
padding: 5px 0;
border-radius: 6px;
/* Position the tooltip text - see examples below! */
position: absolute;
z-index: 1;
}
/* Show the tooltip text when you mouse over the tooltip container */
.tooltip:hover .tooltiptext {
visibility: visible;
}
You could use a popover in Bootstrap if you don't mind adding it to your project. It would require a bit of javascript but should be pretty simple. Most of the functionality of it is handled by Bootstrap.

How can I make an Upvote/Downvote button?

I'm trying to make an upvote/downvote the same way that it's done on SO and Reddit, from what I can see they use arrow images as backgrounds and then position it, but I'm a CSS newbie and I need someone to walk me through it.
You could do it by adding a different picture to the background, one for every state of the button. There is however a cleaner, easier, more modern way of achieving this result: Sprites.
A sprite is an image that is saved as a part of a larger image. One of the biggest advantages of using sprites is the reduction of round-trips to the server for all the images to just one request for the Sprites. The element to display a picture has the image as background. The background is moved relative to the element so the element displays only part of the image. Like when you move a photo-frame over a poster (or in this case: moving the poster under the frame)
At SO they make an image that contains all the states for the button. They give the element for the button (a span in this case) a fixed width and height and add the background to it with CSS. Then toggle a class for the state (on or off) with javascript on the click event. Now the only thing you have to do in CSS is change the position of the background with CSS classes:
for (const btn of document.querySelectorAll('.vote')) {
btn.addEventListener('click', event => {
event.currentTarget.classList.toggle('on');
});
}
.vote {
display: inline-block;
overflow: hidden;
width: 40px;
height: 25px;
cursor: pointer;
background: url('http://i.stack.imgur.com/iqN2k.png');
background-position: 0 -25px;
}
.vote.on {
background-position: 0 2px;
}
Click to vote (using sprites): <span class="sprite vote"> </span>
You can easily add more states to the sprites like 'hover' and 'active' just the same way. SO even puts all the images for the whole page in a single image. You can verify this with firebug or the Chrome developer tools. Look for 'sprites.png'.
Update (2020)
It's been 10 years since I answered this question and in this time,
the landscape has changed. Now you can use inline svg as well to achieve this effect. I've updated the code snippet to use svg. This is how stackoverflow currently does this.
It works by toggling the color property of a surrounding span element on button click. The span element contains an inline svg image of an arrow. The fill property of the path that makes up the arrow is initialized with currentColor, which instructs it to take whatever is the current text color.
for (const btn of document.querySelectorAll('.vote')) {
btn.addEventListener('click', event => {
event.currentTarget.classList.toggle('on');
});
}
.vote {
display: inline-block;
cursor: pointer;
color: #687074
}
.vote.on {
color: #f48024
}
Click to vote (using svg):
<span class="vote">
<svg width="36" height="36">
<path d="M2 10h32L18 26 2 10z" fill="currentColor"></path>
</svg>
</span>
You can do it by using two simple images ... design two images in some image editors like Photoshop, if u don't have MSPaint...
CSS code is
#voting{
width:30px;
height:40px;
}
.upvote{
width:30px;
height: 20px;
cursor: pointer;
}
.downvote{
width:30px;
height: 20px;
background: url('downvote.jpg') 0 0 no-repeat;
cursor: pointer;
}
HTML code :
<div id="voting">
<div class="upvote"></div>
<div class="downvote"></div>
</div>
I'm doing project on django, and I'm trying to implement up-vote and down-vote on many posts, I've taken #Jan's code partly and finished it.
vote.html
<span onclick="like_function({{user_answer.pk}})" id="like-{{user_answer.pk}}" class="vote_up_off"></span>
<div id="counter-{{user_answer.pk}}">0</div>
<span onclick="dislike_function({{user_answer.pk}})" id="dislike-{{user_answer.pk}}" class="vote_down_off"></span>
vote.css
/* like dislike button */
.vote_up_off {
display: inline-block;
overflow: hidden;
width: 40px;
height: 25px;
cursor: pointer;
background: url(' https://i.stack.imgur.com/nxBdX.png');
background-position: 0 -25px;
margin-left: 5px;
}
.vote_up_on {
background-position: 0 2px;
display: inline-block;
overflow: hidden;
width: 40px;
height: 25px;
cursor: pointer;
background: url('https://i.stack.imgur.com/nxBdX.png');
margin-left: 5px;
}
.vote_down_off {
display: inline-block;
overflow: hidden;
width: 40px;
height: 25px;
cursor: pointer;
background: url('https://i.stack.imgur.com/vWw7n.png');
background-position: 0 -1px;
margin-top: 3px;
}
.vote_down_on {
display: inline-block;
overflow: hidden;
width: 40px;
height: 25px;
cursor: pointer;
background: url('https://i.stack.imgur.com/vWw7n.png');
background-position: 0 -28px;
margin-top: 3px;
}
vote.js
function like_function(answer_id) {
var like_button = document.getElementById('like-'+answer_id);
var dislike_button = document.getElementById('dislike-'+answer_id);
var counter_element = document.getElementById('counter-'+answer_id);
let current_counter = parseInt(counter_element.innerText);
//check if dislike is on(true) or off(false)
let dislike_state = false
if (dislike_button.className == "vote_down_on") {
dislike_state = true
}
else {
dislike_state = false
}
//if dislike is checked
if (dislike_state) {
current_counter += 2;
dislike_button.className = 'vote_down_off'
counter_element.innerText = current_counter
like_button.className = 'vote_up_on'
}
// if dislike is not checked
else {
if (like_button.className == 'vote_up_off') {
like_button.className = "vote_up_on"
current_counter += 1;
counter_element.innerText = current_counter
}
else {
like_button.className = "vote_up_off"
current_counter += -1;
counter_element.innerText = current_counter
}
}
}
function dislike_function(answer_id) {
var like_button = document.getElementById('like-'+answer_id);
var dislike_button = document.getElementById('dislike-'+answer_id);
var counter_element = document.getElementById('counter-'+answer_id);
let current_counter = parseInt(counter_element.innerText);
//check if like is on(true) or off(false)
let like_state = false
if (like_button.className == "vote_up_on") {
like_state = true
}
else {
like_state = false
}
//if like is checked
if (like_state) {
console.log('это тру лайк (лайк нажат)')
current_counter += -2;
like_button.className = 'vote_up_off'
counter_element.innerText = current_counter
dislike_button.className = "vote_down_on"
}
//if like is not checked
else {
if (dislike_button.className == 'vote_down_off') {
dislike_button.className = "vote_down_on"
current_counter += -1;
counter_element.innerText = current_counter
}
else {
dislike_button.className = "vote_down_off"
current_counter += 1;
counter_element.innerText = current_counter
}
}
}