How to build sliding horizontal menu. CSS - javascript

I'm trying to build a simple slider that consists of a static 'window' and movable list of items.
where parent container shows only one item and hides all the rest.
I've tried to do something like this but appears this is wrong:
<div id="category-selector">
<div class="categories-list clearfix">
<a class="category">sports</a>
<a class="category">fashion</a>
<a class="category">health</a>
</div>
</div>
#category-selector {
width: 300px; margin: 0 auto; position: relative; z-index: 1;
border: 2px solid #ccc;
-moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; height: 55px;
overflow: hidden;
}
.categories-list {
position: absolute; top: 0; left: 0; display: block;
}
a.category {
display: block; float: left; width: 100%; padding: 10px;
font-size: 30px; font-family: Cambria, 'Segoe UI', sans-serif; line-height: 35px;
text-decoration: none; text-align: center; color: #42a6ce;
}
How do I achieve this functionality?

Try this:
.categories-list {
display: block;
white-space: nowrap;
/*margin-left: -300px;*/
}
a.category {
display: inline-block;
width: 280px;
padding: 10px;
font-size: 30px; font-family: Cambria, 'Segoe UI', sans-serif; line-height: 35px;
text-decoration: none; text-align: center; color: #42a6ce;
}
If you want to have links arranged from left to right, you should set them fixed width. If you set 100% then they will always try to fill container. Setring display to inline-block allows us to avoid wraping line by setting white-space: nowrap; on container.
To scroll it just set margin on container for example margin-left: -300px;
Working sample: http://jsfiddle.net/N9R2E/
Alternatively you may try this:
.categories-list {
display: block;
white-space: nowrap;
margin-left: -300px;
width: 10000px; /* long enough to fit all links */
}
a.category {
display: block;
float:left;
width: 280px;
padding: 10px;
font-size: 30px; font-family: Cambria, 'Segoe UI', sans-serif; line-height: 35px;
text-decoration: none; text-align: center; color: #42a6ce;
}
This uses display:block and float:left like in your attempt, but widths are fixed. To have all links in one line categories-list must be wider then all links together.
Working sample: http://jsfiddle.net/N9R2E/3/

If you don't mind using JS or buttons, this is one way to do it.
$(document).ready(function() {
var slider = $("#categoriese_list");
var leftProperty, newleftProperty;
// the click event handler for the right button
$("#right_button").click(function() {
// get value of current left property
leftProperty = parseInt(slider.css("left"));
// determine new value of left property
if (leftProperty - 100 <= -900) {
newLeftProperty = 0; }
else {
newLeftProperty = leftProperty - 100; }
// use the animate function to change the left property
slider.animate( {left: newLeftProperty}, 1000);
}); // end click
// the click event handler for the left button
$("#left_button").click(function() {
// get value of current right property
leftProperty = parseInt(slider.css("left"));
// determine new value of left property
if (leftProperty < 0) {
newLeftProperty = leftProperty + 100;
}
else {
newLeftProperty = -800;
}
// use the animate function to change the left property
slider.animate( {left: newLeftProperty}, 1000);
}); // end click
}); // end ready
However, I would recommend making your categories list out of a <ul> to keep it more in line.

What you're talking about is essentially a carousel or slider. Rather than trying to code it from scratch I would just use one of the million jQuery plugins out there to build this. I personally like bxslider a lot for things like this because it's responsive and very simple to implement.

Related

How to put an element in hover state when scrolled down using javascript

I am trying to make a div element which when scrolled down will change properties drastically. Here is the codepen example of how I want it to work.
Instead of hover I want it so that when scrolled down, the page wide div will turn into that little circle div which when clicked will function as a back to the top button. It doesn't matter if more classes are added or anything of that sort. I am very new to js and I tried a few things and also googled about it, I got the scroll code from w3school's how to make a back to top button guide which specifies that when scrolled down by 20px the code would react, but I don't know how to turn the JavaScript to JS when scrolled down along with the transformation of the div.
Thanks in advance
I think you want to implement scroll to top functionality, very common these days in most of the web app.
You need to keep below things and design that feature.
There is one header, that should have a reference ID with hash to scroll back to top
Create a button that will always static position (JS) button, will show up when user scroll the window
Bind click event on the button that scroll back to top
Here is the you can see this implementation and use it.
.html
<h1 class="intro-copy">
Scroll down to use this simple back-to-top button made with modern vanilla javascript.
</h1>
<a class="top-link hide" href="" id="js-top">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6"><path d="M12 6H0l6-6z"/></svg>
<span class="screen-reader-text">Back to top</span>
</a>
.css
body {
height: 2000px;
position: relative;
}
.intro-copy {
padding: 1em;
margin: 50vh auto;
max-width: 15em;
font-family: Helvetica;
font-weight: lighter;
font-size: 2em;
line-height: 1.2;
text-align: center;
}
.top-link {
transition: all .25s ease-in-out;
position: fixed;
bottom: 0;
right: 0;
display: inline-flex;
cursor: pointer;
align-items: center;
justify-content: center;
margin: 0 3em 3em 0;
border-radius: 50%;
padding: .25em;
width: 80px;
height: 80px;
background-color: #F8F8F8;
&.show {
visibility: visible;
opacity: 1;
}
&.hide {
visibility: hidden;
opacity: 0;
}
svg {
fill: #000;
width: 24px;
height: 12px;
}
&:hover {
background-color: #E8E8E8;
svg {
fill: #000000;
}
}
}
// Text meant only for screen readers.
.screen-reader-text {
position: absolute;
clip-path: inset(50%);
margin: -1px;
border: 0;
padding: 0;
width: 1px;
height: 1px;
overflow: hidden;
word-wrap: normal !important;
clip: rect(1px, 1px, 1px, 1px);
&:focus {
display: block;
top: 5px;
left: 5px;
z-index: 100000; // Above WP toolbar
clip-path: none;
background-color: #eee;
padding: 15px 23px 14px;
width: auto;
height: auto;
text-decoration: none;
line-height: normal;
color: #444;
font-size: 1em;
clip: auto !important;
}
}
JS:
// Set a variable for our button element.
const scrollToTopButton = document.getElementById('js-top');
// Let's set up a function that shows our scroll-to-top button if we scroll beyond the height of the initial window.
const scrollFunc = () => {
// Get the current scroll value
let y = window.scrollY;
// If the scroll value is greater than the window height, let's add a class to the scroll-to-top button to show it!
if (y > 0) {
scrollToTopButton.className = "top-link show";
} else {
scrollToTopButton.className = "top-link hide";
}
};
window.addEventListener("scroll", scrollFunc);
const scrollToTop = () => {
// Let's set a variable for the number of pixels we are from the top of the document.
const c = document.documentElement.scrollTop || document.body.scrollTop;
// If that number is greater than 0, we'll scroll back to 0, or the top of the document.
// We'll also animate that scroll with requestAnimationFrame:
// https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
if (c > 0) {
window.requestAnimationFrame(scrollToTop);
// ScrollTo takes an x and a y coordinate.
// Increase the '10' value to get a smoother/slower scroll!
window.scrollTo(0, c - c / 10);
}
};
// When the button is clicked, run our ScrolltoTop function above!
scrollToTopButton.onclick = function(e) {
e.preventDefault();
scrollToTop();
}

Display a menu when hovering on the last character in the input in React

I am currently working on a form using React-Bootstrap that has a body that takes a message. This message shall include some tags selected from a dropdown menu. The thing is, this dropdown is to be displayed when the user enters an & and then, the user chooses an option from the menu that will replace the ampersand. I handled almost everything except the part of displayed the menu. How can I always show the menu at the last character entered by the user and also, how can I display it when hovering on this character. For example,
"Hi Dear, today we are going to work on &[The menu has to be displayed here when hovering on the ampersand]"
To be honest, I am quite confused and I just need to figure out how I should start. If there could be anything that helps, I'd be very grateful. Thanks in advance.
Regards.
Here is something i came up with.
To achieve this, first thing i thought of was to detect the caret position inside input or textarea.
I found this library and it worked perfectly.
https://github.com/bubkoo/get-cursor-position
Next task was to figure out how to place a menu inside input or textarea. For that i simply made a parent div and i set input 100% width and height of it & then we can place using any html tag inside that div using position: absolute and it will work like we adding stuff inside input tag.
The menu was added with top & left i got using that library. Rest of the code is basic, you can simple figure that out just checking it below.
Here is the code:
const menu = document.querySelector('.menu')
function showMenu(element) {
let lastChar = element.value[element.value.length - 1],
caret = getCaretCoordinates(element, element.selectionEnd);
if (lastChar === "&") {
menu.style.display = 'block';
menu.style.left = caret.left + 20 + 'px'
menu.style.top = caret.top + 20 + 'px'
} else {
menu.style.display = 'none'
}
}
function copyText(text) {
const input = document.querySelector('#input')
input.value += " " + text
menu.style.display = 'none'
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: Arial, Helvetica, sans-serif;
transition: all 0.3s ease;
}
body {
height: 100vh;
width: 100vw;
display: grid;
place-content: center;
background-color: blueviolet;
}
.parent {
position: relative;
width: 500px;
height: 120px;
}
#input {
background-color: white;
width: 100%;
height: 100%;
border: none;
border-radius: 10px;
padding: 20px;
}
#input:focus {
border: 0;
outline: none;
}
.menu {
display: none;
position: absolute;
background-color: black;
color: white;
width: 100px;
}
.menu li {
text-align: center;
cursor: pointer;
height: 60px;
list-style: none;
display: grid;
place-content: center;
padding: 10px;
}
li:hover {
background: white;
;
color: black;
border: 1px solid black
}
<div class="parent">
<textarea id="input" oninput="showMenu(this)"></textarea>
<div class="menu">
<li onclick='copyText(this.innerText)'>Mango</li>
<li onclick='copyText(this.innerText)'>Banana</li>
<li onclick='copyText(this.innerText)'>Apple</li>
<li onclick='copyText(this.innerText)'>Orange</li>
<li onclick='copyText(this.innerText)'>Grapes</li>
</div>
</div>
<script src="https://rawgit.com/component/textarea-caret-position/master/index.js"></script>

CSS Formula for Precisely Offsetting Text

On my website, I am aligning a body of text precisely as exemplified in the following snippet.
html, body {
width: 100%;
height: 100%;
font-family: arial;
font-size: 48px;
text-transform: uppercase;
}
body {
margin: 0;
background: skyblue;
}
div {
width: 200px;
height: 100vh;
padding-top: calc(100vh - (1.5rem * 1.35));
box-sizing: border-box;
border: solid red 1px;
}
span {
line-height: 1.35;
display: inline-block;
border: solid black 1px;
}
<div><span>This</span> <span>is</span> <span>a</span><span>body</span><span>of</span> <span>text.</span></div>
However, I was hoping to take it one step further. For instance, I want to be able to place the top of the text as close as possible to, say, 60vh from the top of the page while still displaying half of the last line. Below is an example of what I mean in JS.
Note: Just noticed the second snippet does not display properly unless you open it to edit it. If you transfer it to codepen, it should work properly.
const
div = document.querySelector('div'),
span = document.querySelector('span'),
lineHeight = parseFloat(getComputedStyle(span).lineHeight),
target = innerHeight * 0.6,
remainder = (innerHeight - target) / lineHeight % 1 * lineHeight
div.style.paddingTop = target + remainder - lineHeight / 2 + 'px'
html, body {
width: 100%;
height: 100%;
font-family: arial;
font-size: 48px;
text-transform: uppercase;
}
body {
margin: 0;
background: skyblue;
}
div {
width: 200px;
height: 100vh;
position: absolute;
box-sizing: border-box;
border: solid red 1px;
}
span {
line-height: 1.5;
display: inline-block;
border: solid black 1px;
}
<div><span>This</span> <span>is</span> <span>a</span> <span>body</span> <span>of</span> <span>text.</span></div>
Notably, I know you can obviously find the "remainder" using calc, viewport units, and rem, but the rest is what is confusing because I am not great at math and also lacking sleep.
Hence I was hoping that somebody out there, who is better at math than me, would be able to tell me whether or not a pure CSS solution without preprocessors is possible (i.e. using only calc, viewport units, rem units, etc) before I waste any more time thinking about this. I know there are some nifty CSS formulas for fluid typography, but is something like this possible?
[ edit ] I thought about this some more while laying in bed. I do not believe it is possible without being able to calculate the "remainder." And there does not seem to be any way to calculate the "remainder" with only addition, subtraction, multiplication, and division. Please correct me if I am wrong.
The goal is to have the DIV tag be 100% of the document's height and then the text is offset a little bit within the DIV?
I think just adding another tag within the DIV to offset all the text can work. You said you want 60vh. Line Height should also be used when dealing with text height.
html, body {
width: 100%;
height: 100%;
font-family: arial;
font-size: 48px;
text-transform: uppercase;
}
body {
margin: 0;
background: skyblue;
}
div {
width: 200px;
height: 100vh;
box-sizing: border-box;
border: solid red 1px;
}
p
{ margin: 0;
padding-top: 60vh;
margin-top: -0.8em;
line-height: 1.6em;
}
span {
line-height: 1.35;
display: inline-block;
border: solid black 1px;
}
<html>
<body>
<div><p><span>This</span> <span>is</span> <span>a</span><span>body</span><span>of</span> <span>text.</span></p></div>
</body>
</html>
Or is this not quite it?

How do I move others divs around upon clicking my jQuery event?

I have inserted a jQuery event into my webpage which allows for a div in my page to expand to reveal more content. I'm having a problem with the surrounding divs not moving down to accommodate for the space needed to display the expanded div.
I initially tested this div in a separate document and found it to work successfully without too much fuss. I worked with other divs to be sure that they'd move upon clicking the event. Upon inserting the same code into my already developed web page however, the surrounding divs remain fixed and the expansion works behind those divs. Why might this be? Could it be that one of my divs beneath the expanded one is somehow fixed?
I researched the CSS property 'position' but can't make any link between these contributing to the problem.
Incase the problem relates to that of my expanded div (instead of the surrounding divs), I shall only post the code for the HTML, CSS & Javascript/jQuery that directly relates to that particular part of my webpage. Please request any further code if you feel it's necessary.
Thank you for taking time to read.
Here is my code:
HTML
<div id="showmorelocations-container"><p>More Locations</p>
<div class="toggler-expand">
</div>
</div>
CSS
#showmorelocations-container {
height: 100px;
line-height: 150px;
width: auto;
margin: auto;
margin-bottom: 50px;
}
#showmorelocations-container p {
text-align: center;
font-family: 'Hind', sans-serif;
font-size: 20px;
font-weight: bold;
text-decoration: none;
position: relative;
top: 50%;
transform: translateY(-50%);
line-height: 100px;
}
.toggler-expand {
height: 400px;
width: auto;
background-color: #FFBBBB;
display: none;
margin-top: -25px;
}
jQuery
$(function() {
$('#showmorelocations-container').click(function() {
$(this).find('.toggler-expand').slideToggle();
});
});
The issue is most likely related to the fact that you have set a fixed height for your parent container and try to expand the a child.
Change the following line:
#showmorelocations-container {
height: 100px; // change px to %
...
}
to
#showmorelocations-container {
height: 100%;
...
}
in order to allow the parent to expand if the child expands too.
Check the fiddle here: https://jsfiddle.net/n1dwz8v1/
Is this the behavior you are looking for?
$( document ).ready(function() {
$('#showmorelocations-container').click(function() {
$(this).find('.toggler-expand').slideToggle();
});
});
#showmorelocations-container {
height: 100px;
line-height: 150px;
width: auto;
margin: auto;
margin-bottom: 50px;
background-color:#ccc
}
#showmorelocations-container p {
text-align: center;
font-family: 'Hind', sans-serif;
font-size: 20px;
font-weight: bold;
text-decoration: none;
position: relative;
top: 50%;
transform: translateY(-50%);
line-height: 100px;
}
.toggler-expand {
height: 400px;
width: auto;
background-color: #FFBBBB;
display: none;
margin-top: -25px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="showmorelocations-container">
<p>More Locations</p>
<div class="toggler-expand">
<p>Content</p>
</div>
</div>
use this :
$(function() {
$('#showmorelocations-container p').click(function() {
$(this).parent().find('.toggler-expand').slideToggle();
});
});

Show one element if another is above a certain height

I have a following HTML:
<span class="day-number">{{day-number}}</span>
<div class="event-box">
<div class="event-container">
</div>
<div class="more-events">more ...</div>
</div>
Event-container is filled with an unknown number of .event elements like the following:
<div class="event">{{event-name}}</div>
I want to show or hide the .more element based on if the .event-container has a height of over 76px (equal to the height of four .event elements stacked).
The styling for the above elements:
.event {
text-align: left;
font-size: .85em;
line-height: 1.3;
border-radius: 3px;
border: 1px solid #3a87ad;
background-color: #3a87ad;
font-weight: normal;
color: whitesmoke;
padding: 0 1px;
overflow: hidden;
margin-bottom: 2px;
cursor: pointer;
}
.event-box {
max-height: 76px;
overflow: hidden;
position:relative;
}
.event-box .more-events {
height: 10px;
position: absolute;
right: 0;
bottom: 10px;
display: none;
z-index: 5;
}
No styling for .event-container
I can do what I want with Javascript (jQuery):
$(".event-box").each(function(){
var $this = $(this);
if($this.children(".event-container").height() > 76){
$this.children(".more-events").css("display", "block");
} else {
$this.children(".more-events").css("display", "");
}
});
And run that every time a make a change, but I'd rather do it with CSS.
Is this possible? Maybe with pseudo elements or media queries or something?
JSFIDDLE: http://jsfiddle.net/pitaj/LjLxuhx2/
If changing the markup is acceptable there is a possibility to achieve a somewhat similarly looking page without using JavaScript to show or hide, here is the Fiddle
I have removed <div class="more-events">more ...</div> line and made elements of event class to get hide when it is necessary I also made them to appear when hovering over more ... .
The CSS I have added:
.event:nth-child(n){
display: none;
}
.event:nth-child(1),.event:nth-child(2),.event:nth-child(3),.event:nth-child(4){
display: block;
}
.event:nth-child(5){
text-indent: -9999px;
position: relative;
display: block;
color: black;
border: none;
background-color: #FFF;
}
.event:nth-child(5)::before{
position: absolute;
text-indent: 0px;
content: "more ...";
display: block;
}
.event:nth-child(5):hover{
position: static;
text-indent: 0;
border: 1px solid #3a87ad;
background-color: #3a87ad;
color: whitesmoke;
}
.event:nth-child(5):hover::before{
display:none;
}
.event:nth-child(5):hover ~ .event:nth-child(n){
display: block;
}
And for .event-box class I have commented out max-height: 76px; because in my browser 76px was not equal to the height of four .event elements stacked. Also removed update function.
I dont think it's possible using css only. but for better approach in what you are trying to do.instead of using max-height for .event-box I use this css which is add display:none to +4.event on your event container:
.event-box .event-container .event:nth-child(n+5){
display: none;
}
and now when it's more than 4 .event your more text appears. FIDDLE
UPDATE:
HERE I make little change in you js as well and make it more professional,
while you are using template to render the page, maybe you can do it as follow
<div class="event-container">
{{#each events}}
<div class="event">{{event-name}}</div>
{{/each}}
</div>
{{#if canshowmore}}
<div class="more-events">more ...</div>
{{/if}}
and
function canshowmore() {
return events.length >= 4;
}

Categories

Resources