What CSS would I have to add to format chat app? - javascript

I'm trying to style a basic chat app, nothing too fancy or over the top, but I'm running into a few issues. There are three goals that I have with styling:
Have the blue messages (you) align to the right, and the gray messages align (other user) to the left.
Have messages pop up on the bottom of the div, with each subsequent message moving an older one up.
Have the div scroll once the messages exceeded the height in pixels.
This is the code I have thus far:
const API_URL = "http://localhost:3000"
const form = document.querySelector("form")
const chatbox = document.querySelector(".chatbox")
const chatInput = document.querySelector(".message-input")
const socket = io.connect(API_URL)
socket.on("chat-message", (data) => {
console.log(data)
appendMessage("other-message", data)
})
socket.on("disconnect", (reason) => {
socket.emit("disconnect", reason)
});
form.addEventListener("submit", e => {
e.preventDefault()
console.log("message: ", chatInput.value)
const message = chatInput.value
appendMessage("message", message)
socket.emit("send-chat-message", message)
form.reset()
})
function appendMessage(className, message){
const div = document.createElement('div')
div.append(message)
div.className = className
chatbox.append(div)
}
.wrapper{
display: grid;
grid-template-columns: 1fr 2fr;
height: 100vh;
width: 100vw;
}
.side-bar{
background-color: blue;
color: gray;
text-align: left;
padding: 20px;
font-size: 50px;
}
.chat-room:hover{
cursor: pointer;
color: white;
}
.messages-container{
display: grid;
grid-template-columns: auto;
grid-template-rows: auto 40px;
}
.chatbox{
background-color: black;
border: 1px solid white;
overflow: scroll;
}
.chatbox > div{
border-radius: 15px;
padding: 10px;
margin: 20px;
color: white;
width: fit-content;
max-width: 50%;
}
.message{
background-color: blue;
}
.other-message{
background-color: gray;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<title>chat</title>
</head>
<body>
<div class = "wrapper">
<div class="side-bar">
<div class="name">
</div>
<div class="chat-room">
<h3>#chat room 1</h3>
</div>
<div class="chat-room">
<h3>#chat room 2</h3>
</div>
<div class="chat-room">
<h3>#chat room 3</h3>
</div>
<div class="chat-room">
<h3>#lifetime chat</h3>
</div>
</div>
<div class="messages-container">
<!-- Chat messages will be appended here! -->
<div class="chatbox">
</div>
<form>
<input type="text" class="message-input form-control" required name="send-message" placeholder="Send message" aria-label="Recipient's username" aria-describedby="basic-addon2">
</form>
</div>
</div>
<script src="https://cdn.socket.io/socket.io-3.0.1.min.js"></script>
<script src="sendMessage.js"></script>
</body>
</html>
The issues I'm having currently is that whenever I the amount of messages exceeds the height of the "chat" div in the HTML file, the div does not overflow, and instead grows indefinitely. I'm not sure what's causing this, even though I added the code for overflow: scroll; in the css for that particular div. Also, I'm not sure how to push the messages to the bottom of the div as opposed to the top, and have each new one push the previous one up.
Are there any css tricks I can use to accomplish those three goals?

For overflow: scroll to work, you need to explicitly set the divs height. In this case, I used calc to make it 100vh and subtracted the height of the form.
For it to scroll from the bottom up, you can use element.scrollTo and set it to the height of the .chatbox div each time:
const API_URL = "http://localhost:3000"
const form = document.querySelector("form")
const chatbox = document.querySelector(".chatbox")
const chatInput = document.querySelector(".message-input")
const socket = io.connect(API_URL)
socket.on("chat-message", (data) => {
console.log(data)
appendMessage("other-message", data)
})
socket.on("disconnect", (reason) => {
socket.emit("disconnect", reason)
});
form.addEventListener("submit", e => {
e.preventDefault()
console.log("message: ", chatInput.value)
const message = chatInput.value
appendMessage("message", message)
socket.emit("send-chat-message", message)
form.reset()
chatbox.scrollTo(0, chatbox.scrollHeight)
})
function appendMessage(className, message) {
const div = document.createElement('div')
div.append(message)
div.className = className
chatbox.append(div)
}
.wrapper {
display: grid;
grid-template-columns: 1fr 2fr;
height: 100vh;
width: 100vw;
}
.side-bar {
background-color: blue;
color: gray;
text-align: left;
padding: 20px;
font-size: 50px;
}
.chat-room:hover {
cursor: pointer;
color: white;
}
.messages-container {
display: grid;
grid-template-columns: auto;
grid-template-rows: auto 40px;
}
.chatbox {
height: calc(100vh - 40px);
background-color: black;
border: 1px solid white;
overflow: scroll;
}
.chatbox>div {
border-radius: 15px;
padding: 10px;
margin: 20px;
color: white;
width: fit-content;
max-width: 50%;
}
.message {
background-color: blue;
}
.other-message {
background-color: gray;
}
input {
height: 40px;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<div class="wrapper">
<div class="side-bar">
<div class="name">
</div>
<div class="chat-room">
<h3>#chat room 1</h3>
</div>
<div class="chat-room">
<h3>#chat room 2</h3>
</div>
<div class="chat-room">
<h3>#chat room 3</h3>
</div>
<div class="chat-room">
<h3>#lifetime chat</h3>
</div>
</div>
<div class="messages-container">
<!-- Chat messages will be appended here! -->
<div class="chatbox">
</div>
<form>
<input type="text" class="message-input form-control" required name="send-message" placeholder="Send message" aria-label="Recipient's username" aria-describedby="basic-addon2">
</form>
</div>
</div>
<script src="https://cdn.socket.io/socket.io-3.0.1.min.js"></script>

CSS Grid has this little quirk that grid children have a min-height and min-width set to auto. This will cause the grid to stretch whenever the content exceeds the container. Setting min-height: 0; will prevent this behavior and allow the overflow to happen.
Read this SO answer for more details.
I've added an inner container to your chatbox element. The chatbox element now functions as an overflow wrapper. The inner element will be the wrapper of the chat messages. Since you want the messages to appear at the bottom you'll need to push this inner element down so that it will keep the messages at the bottom of the screen. The pushing down can be accomplished with display: grid; and align-items: end;. Flexbox seemed like a better candidate, but it disabled the ability to scroll. Grid does not.
Within the inner element use Flexbox to position a chat message either left or right and in a column formation.
Finally after appending each message use chatbox.scrollTo(0, chatbox.scrollHeight) to force the chatbox element to scroll down after each message that is appended to the document.
const API_URL = "http://localhost:3000"
const form = document.querySelector("form")
const chatbox = document.querySelector(".chatbox")
const chatboxInner = document.querySelector(".chatbox-inner")
const chatInput = document.querySelector(".message-input")
const socket = io.connect(API_URL)
socket.on("chat-message", (data) => {
console.log(data)
appendMessage("other-message", data)
})
socket.on("disconnect", (reason) => {
socket.emit("disconnect", reason)
});
form.addEventListener("submit", e => {
e.preventDefault()
console.log("message: ", chatInput.value)
const message = chatInput.value
appendMessage("message", message)
socket.emit("send-chat-message", message)
form.reset()
})
function appendMessage(className, message) {
const div = document.createElement('div')
div.append(message)
div.className = className
chatboxInner.append(div)
chatbox.scrollTo(0, chatbox.scrollHeight)
}
// Dummy messages for demo.
setInterval(() => {
appendMessage('other-message', 'Testing')
}, 4000)
.wrapper {
display: grid;
grid-template-columns: 1fr 2fr;
height: 100vh;
width: 100vw;
}
.side-bar {
grid-area: 1 / 1 / 2 / 2;
background-color: blue;
color: gray;
text-align: left;
padding: 20px;
font-size: 50px;
}
.chat-room:hover {
cursor: pointer;
color: white;
}
.messages-container {
grid-area: 1 / 2 / 2 / 3;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr 40px;
min-height: 0;
}
.chatbox {
display: grid;
align-items: end;
background-color: black;
border: 1px solid white;
overflow: scroll;
}
.chatbox-inner {
display: flex;
flex-direction: column;
justify-content: flex-end;
width: 100%;
padding: 10px 0;
}
.chatbox-inner > div {
border-radius: 15px;
padding: 10px;
color: white;
width: fit-content;
max-width: 50%;
}
.chatbox-inner > .message {
background-color: blue;
margin: 10px 20px 10px auto;
}
.chatbox-inner > .other-message {
background-color: gray;
margin: 10px auto 10px 20px;
}
.as-console-wrapper {
display: none !important;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<title>chat</title>
</head>
<body>
<div class="wrapper">
<div class="side-bar">
<div class="name">
</div>
<div class="chat-room">
<h3>#chat room 1</h3>
</div>
<div class="chat-room">
<h3>#chat room 2</h3>
</div>
<div class="chat-room">
<h3>#chat room 3</h3>
</div>
<div class="chat-room">
<h3>#lifetime chat</h3>
</div>
</div>
<div class="messages-container">
<!-- Chat messages will be appended here! -->
<div class="chatbox">
<div class="chatbox-inner">
</div>
</div>
<form>
<input type="text" class="message-input form-control" required name="send-message" placeholder="Send message" aria-label="Recipient's username" aria-describedby="basic-addon2">
</form>
</div>
</div>
<script src="https://cdn.socket.io/socket.io-3.0.1.min.js"></script>
<script src="sendMessage.js"></script>
</body>
</html>

Related

Why is my div not expanding in width 100%?

I am creating a sidebar menu composed by 3 divs, these 3 divs should expand in "width" 100% of the menu width but they don't. I have checked to make sure that all tags/divs are closed and make sure that are all displayed as grid and put on each width 100% but still they don't expand to 100% width of their container. Why is that and how to fix it?
Here is my code:
*,
html {
margin: 0;
border: 0;
box-sizing: border-box;
color: #fff;
font-family: pc_seniorregular;
font-weight: 400;
}
.mobile,
.tablet,
.laptop {
display: none;
}
body {
height: 100vh;
width: 100vw;
overflow: hidden;
background-color: #16202a;
/* border: 5px solid blue; */
}
div,
menu,
header,
footer {
border: dotted 2px yellow;
display: grid;
height: 100%;
width: 100%;
}
.desktop {
height: 100%;
width: 100%;
/* border: 5px solid greenyellow; */
}
.dash-desk-wrap {
grid-template-columns: 1fr 4fr;
height: 100%;
width: 100%;
/* border: 5px solid red; */
}
/* SIDEBAR */
/* SIDEBAR */
/* SIDEBAR */
.dash-desk-sidebar {
display: grid;
grid-template-rows: 0.7fr 7fr 1fr;
height: 100%;
width: 100%;
border: 5px dotted blue;
}
.dash-desk-side-logo {
border: 3px dotted beige;
}
.dash-desk-side-list {
border: 3px dotted red;
}
.dash-desk-side-social {
border: 3px dotted green;
}
/* MAIN */
/* MAIN */
/* MAIN */
.dash-desk-main-wrap {
grid-template-rows: 0.5fr 1fr 4fr 0.5fr;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<link href='http://fonts.googleapis.com/css?family=Lato:400,700' rel='stylesheet' type='text/css'>
<title>Base Template</title>
</head>
<body>
<div class="mobile">
<h1>mobile</h1>
</div>
<div class="tablet">
<h1>tablet</h1>
</div>
<div class="laptop">
<h1>laptop</h1>
</div>
<div class="desktop">
<div class="dash-desk-wrap">
<!-- SIDEBAR -->
<!-- SIDEBAR -->
<!-- SIDEBAR -->
<menu class="dash-desk-sidebar">
<div class="dash-desk-side-logo">
<p>Logo</p>
</div>
<div class="dash-desk-side-list">
<p>Side</p>
</div>
<div class="dash-desk-side-social">
<p>Social</p>
</div>
</menu>
<!-- MAIN -->
<!-- MAIN -->
<!-- MAIN -->
<div class="dash-desk-main-wrap">
<header></header>
<div></div>
<div></div>
<footer></footer>
</div>
</div>
</div>
</body>
</html>
Either make the menu class as div
<div class="dash-desk-sidebar">
<div class="dash-desk-side-logo">
<p>Logo</p>
</div>
<div class="dash-desk-side-list">
<p>Side</p>
</div>
<div class="dash-desk-side-social">
<p>Social</p>
</div>
</div>
or make a div below menu uwing the same.
Looking at your layout in code inspector it looks like browsers add default padding to menus.
For example, Google Chrome adds a padding-inline-start: 40px to <menu> elements.
Therefore, you can remove it by either declaring
.dash-desk-sidebar {
padding-inline-start: 0;
}
or
.dash-desk-sidebar {
padding: 0;
}
Alternatively, you can use a div instead of a menu.
If I understand you correctly you just have to add padding: 0 to .dash-desk-sidebar, because it has a "left padding" at the moment.
.dash-desk-sidebar {
padding: 0;
}

How can I erase the specific container?

I am trying to make a to-do list by myself and it's going pretty well, but I can't remove the correct div. It always removes the first one in the pile. I am not creating new divs, I am basically cloning a template that I've made and setting the display as none.
let d = document.getElementById('botao')
d.addEventListener('click', addTarefa())
function addTarefa() {
let divtarefa = document.getElementById('TarefaEscondida')
clone = divtarefa.cloneNode(true)
clone.id = 'tarefa'
clone.class = "tarefa"
container.appendChild(clone)
clone.setAttribute('display', 'flex')
clone.setAttribute('class', 'tarefa')
clone.setAttribute('id', 'tarefa')
}
function suma() {
let father = document.getElementById('container')
let son = document.getElementById('tarefa')
let apaga = father.removeChild(son)
}
* {
margin: 0;
box-sizing: border-box;
}
body {
background-color: aqua;
}
header {
text-align: center;
background-color: rgb(255, 208, 0);
}
#container {
display: flex;
background-color: beige;
margin-top: 15px;
margin-left: 15%;
margin-right: 15%;
height: 90vh;
align-items: stretch;
padding-top: 8px;
flex-direction: column;
flex-wrap: nowrap;
gap: 8px;
}
.tarefa {
padding: 5px;
background-color: brown;
margin-left: 8px;
margin-right: 8px;
display: flex;
}
.texto {
border: none;
margin-left: 8px;
background-color: brown;
color: white;
width: 90%;
padding: 8px;
}
::placeholder {
color: white;
opacity: 1;
}
.remove {
float: right;
height: 40px;
width: 40px;
color: #333;
cursor: pointer;
}
#botao {
position: fixed;
background-color: brown;
height: 80px;
width: 80px;
border-radius: 50%;
bottom: .8%;
left: 1.5%;
text-align: center;
color: white;
font-weight: 900;
font-size: 4.5rem;
}
#TarefaEscondida {
padding: 5px;
background-color: brown;
/* margin-top: 8px; */
margin-left: 8px;
margin-right: 8px;
display: none;
}
#TextoEscondido {
border: none;
margin-left: 8px;
background-color: brown;
color: white;
width: 90%;
padding: 8px;
}
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>My To Do list</title>
</head>
<body>
<header id="header">
<h1>My To do list</h1>
</header>
<main id="container">
<div id="TarefaEscondida">
<input type="button" value="Feito" class="remove" onclick="suma()">
<input type="text" placeholder="Escreva aqui..." id="TextoEscondido">
</div>
<div id='tarefa' class="tarefa">
<input type="button" value="Feito" class="remove" onclick="suma()">
<input type="text" placeholder="Escreva aqui..." class="texto">
</div>
</main>
<div id="botao" onclick="addTarefa()">
<P>+ </P>
</div>
<script src="main.js"></script>
</body>
</html>
You don't need to bother with element IDs. DOM navigation will allow you to find the parent of the clicked element, and remove it:
<main id="container">
<div id="TarefaEscondida">
<input type="button" value="Feito" class="remove" onclick="suma(this)">
<input type="text" placeholder="Escreva aqui..." id="TextoEscondido">
</div>
<div id='tarefa' class="tarefa">
<input type="button" value="Feito" class="remove" onclick="suma(this)">
<input type="text" placeholder="Escreva aqui..." class="texto">
</div>
</main>
(Notice how I've changed the onclick so it passes this element)
And then your remove function can simply locate the parent of the clicked element and remove it.
function suma(element) {
element.parentNode.remove();
}
Also, please note: In your function that adds a new element, you should be aware of duplicating element IDs. That will create invalid HTML because IDs must be unique.
Here is a Fiddle example.
let d = document.getElementById('botao')
d.addEventListener('click', addTarefa())
function addTarefa() {
let divtarefa = document.getElementById('TarefaEscondida')
clone = divtarefa.cloneNode(true)
clone.id = 'tarefa'
clone.class = "tarefa"
container.appendChild(clone)
clone.setAttribute('display', 'flex')
clone.setAttribute('class', 'tarefa')
clone.setAttribute('id', 'tarefa')
}
function suma(element) {
element.parentNode.remove();
}
<main id="container">
<div id="TarefaEscondida">
<input type="button" value="Feito" class="remove" onclick="suma(this)">
<input type="text" placeholder="Escreva aqui..." id="TextoEscondido">
</div>
<div id='tarefa' class="tarefa">
<input type="button" value="Feito" class="remove" onclick="suma(this)">
<input type="text" placeholder="Escreva aqui..." class="texto">
</div>
</main>
<div id="botao" onclick="addTarefa()">
<P>+ </P>
</div>
In .addEventListener you put function but don't call it.
d.addEventListener('click',addTarefa)

HTML/JS Kanban Board doesn't let me drop newly created tasks into other columns

I am creating a Kanban Board in HTML/JS/CSS and am close to finishing my MVP here. Everything is working as expected, except for one thing. When I create a new task, I am able to drag it (seemingly) but not DROP it into any other columns. The sample tasks I have do not have this problem and I am ripping my hair out trying to figure out what the issue is. When I attempt to drag and drop newly created tasks into other columns, I get this error:
TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
at drop (/script.js:31:13)
at HTMLDivElement.ondrop (/:45:112)
I am using basic drag and drop API stuff for HTML and JS and literally only need to make this work in order to finish my MVP. Any help is appreciated. NOTE: The line numbers in the above error change based on what column I try to drop the new task into but the error itself stays the same.
Here is my code:
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Christopher's Kanban Board</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="new-task-window" id="new_task_form">
<div class="header">
<div class="title">New Task</div>
<button class="btn-close-window" data-target="#new_task_form">X</button>
</div>
<div class="body">
<input type="text" id="new-task-name" />
<input type="submit" value="New Task" id="new-task-submit" />
</div>
</div>
<!--Kanban Board-->
<div class="kanban-container">
<div class="kanban-container-section" id="todo" ondrop="drop(event)" ondragover="allowDrop(event)">
<strong>To Do</strong>
<div class="task-button-block">
<button class="task-button" id="task-button" data-target="#new_task_form">+ New Task</button>
</div>
<div class="task" id="task1" draggable="true" ondragstart="drag(event)">
<span contenteditable="true">Task #1</span>
<!--<button class="edit_button" id="edit_button">Edit</button>-->
</div>
<div class="task" id="task2" draggable="true" ondragstart="drag(event)">
<span contenteditable="true">Task #2</span>
</div>
<div class="task" id="task3" draggable="true" ondragstart="drag(event)">
<span contenteditable="true">Task #3</span>
</div>
<div class="task" id="task4" draggable="true" ondragstart="drag(event)">
<span contenteditable="true">Task #4</span>
</div>
</div>
<div class="kanban-container-section" id="inprogress" ondrop="drop(event)" ondragover="allowDrop(event)">
<strong>In Progress</strong>
</div>
<div class="kanban-container-section" id="done" ondrop="drop(event)" ondragover="allowDrop(event)">
<strong>Done</strong>
</div>
<div class="kanban-container-section" id=" blocked" ondrop="drop(event)" ondragover="allowDrop(event)">
<strong>Blocked</strong>
</div>
</div>
<div id="overlay"></div>
<script src="script.js"></script>
</body>
</html>
script.js:
const task = document.querySelector('.task');
const buttons = document.querySelectorAll("[data-target]");
const close_buttons = document.querySelectorAll(".btn-close-window");
//Allow the New Task Button to open the New Task Creation Window.
buttons.forEach(btn => {
btn.addEventListener('click', () => {
document.querySelector(btn.dataset.target).classList.add("active");
overlay.classList.add("active");
});
});
close_buttons.forEach((btn) => {
btn.addEventListener('click', () => {
document.querySelector(btn.dataset.target).classList.remove("active");
overlay.classList.remove("active");
});
});
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
const new_task_submit = document.getElementById("new-task-submit");
if(new_task_submit) {
new_task_submit.addEventListener('click', createTask);
}
function createTask() {
const task_div = document.createElement("div");
const input_value = document.getElementById("new-task-name").value;
//Take the text from the above input and create a task with that text.
const text = document.createTextNode(input_value);
task_div.appendChild(text);
//Add the proper class (task in this case) to the newly created task.
task_div.classList.add("task");
//Add the draggable attribute to the newly created task and set it to true to allow drag and drop.
if(task_div){
task_div.setAttribute("draggable", "true");
task_div.setAttribute("contenteditable", "true");
}
//task_div.innerHTML += `
//<div class="task" id="${input_value.toLowerCase().split(" ").join("")}"
//draggable="true" ondragstart="drag(event)>
//<span contenteditable="true">${input_value}</span>
//</div>
//`
//Add the new task to the To Do section of the Kanban Board.
const todo = document.getElementById("todo");
todo.appendChild(task_div);
document.getElementById("new-task-name").value = "";
new_task_form.classList.remove("active");
overlay.classList.remove("active");
}
style.css (the error would indicate that this file is not the problem):
.kanban-container {
display: grid;
grid-auto-columns: 250px;
grid-auto-flow: column;
grid-gap: 8px;
height: 100vh;
overflow: auto;
}
.kanban-container-section {
background: #EBEBEB;
border-radius: 3px;
display: grid;
grid-auto-rows: max-content;
grid-gap: 10px;
padding: 10px;
}
.kanban-container-section strong {
background: #2C89BF;
font-size: 16px;
margin: 0 0 12px 0;
padding: 10px;
}
.task {
background: #FFFFFF;
box-shadow: 0 1px 0 rgba(9,30,66,.25);
border-radius: 3px;
padding: 10px;
}
.task-button {
width: 40%;
background: #FFFFFF;
border-radius: 3px;
box-shadow: 0 1px 0 rgba(9,30,66,.25);
border: 0.1rem;
cursor: pointer;
}
.task.button:active {
transform: scale(0.9);
}
.btn-close-window {
padding: 0.5rem 1rem;
border: 1px solid #ccc;
border-radius: 3px;
cursor: pointer;
}
.new-task-window {
width: 450px;
position: fixed;
top: -50%;
left: 50%;
transform: translate(-50%, -50%);
border: 1px solid #ccc;
z-index: 2;
background-color:#FFFFFF;
}
.new-task-window.active {
top: 15%;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.5rem 1rem;
background-color: rgba(0, 0, 0, 0.03);
border-bottom: 1px solid #ccc;
}
#overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.2);
}
#overlay.active {
display: block;
}
#new-task-name, #new-task-submit {
padding: 1rem 1rem;
width: 90%;
margin: 0.25rem;
align-items: center;
}
#new-task-submit {
background-color: #2C89BF;
border: none;
color: #FFFFFF;
align-items: center;
}
Again, if anyone knows what my issue is here, the help is greatly appreciated. Thanks!

JQuery Product Slider Errors

I am new to JQuery and am trying to create a product slider for my website. I was having some troubles so I made a basic version of it in this question. For some reason I am having no luck in getting it to work and have no idea why.
The three product boxes will animate as a section rather than individually, similar to this one https://smartslider3.com/product-carousel/. The animation will go from right to left when clicking the previous button and left to right when clicking the next button but I have just left it as slide up and slide down at the moment because I don't know the correct code for the animation. Touch swipe support would also be nice to have.
$( document ).ready(function() {
$("#slider-next-button").click(function(){
var currentSlider = $(".active");
var nextSlide = currentSlider.next();
currentSlider.slideDown(2000);
currentSlider.removeClass(active);
nextSlide.slideUp(2000);
nextSlide.slideUp(2000);
})
});
;
.content{
width: 80%;
margin: auto;
}
.slider-section{
background-color: lightgrey;
height: 600px;
padding: 50px 0px 0px 0px;
}
.slider-container{
display: grid;
grid-template-columns: 1fr 12fr 1fr;
grid-column-gap: 20px;
}
.slider-previous-button{
height: 40px;
border-radius: 20px;
background-color: grey;
cursor: pointer;
}
.slider-next-button{
height: 40px;
border-radius: 20px;
background-color: grey;
cursor: pointer;
}
.slider-items{
display: none;
grid-template-columns: 1fr 1fr 1fr;
grid-column-gap: 20px;
}
.slider-items.active{
display: grid;
}
.slider-item{
background-color: blue;
height: 400px;
}
<!DOCTYPE html>
<html>
<head>
<title>Slider Test</title>
<link rel="stylesheet" type="text/css" href="css/slidertest.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="js/slidertest.js"></script>
</head>
<body>
<div class="slider-section">
<div class="content">
<div class="slider-container">
<div class="slider-previous-button"><p></p></div>
<div class="slider-items active">
<div class="slider-item">1</div>
<div class="slider-item">2</div>
<div class="slider-item">3</div>
</div>
<div class="slider-next-button"><p></p></div>
<div class="slider-items">
<div class="slider-item">4</div>
<div class="slider-item">5</div>
<div class="slider-item">6</div>
</div>
<div class="slider-items">
<div class="slider-item">7</div>
<div class="slider-item">8</div>
<div class="slider-item">9</div>
</div>
</div>
</div>
</div>
</body>
</html>

Responsive 3 column page with sidebars click to hide

I am trying to create a similar design/approach to this:
https://help.sap.com/viewer/8092b085a68941f6aaa6708685a62b0d/4.2.8/en-US/acc57dbca1ab4a5bac2a352ce8cc52d8.html?q=Amazon
Notice that, when the sidebar << and >> icons are clicked, those sidebars slide out and the topic/content in the center expands to take the freed up space.
They're using AngularJS but I have to do this using html. I can use jquery, vanilla js, and if it makes sense I can try bootstrap (though I'm obviously not very experienced and want to stick to just html and jquery if possible).
Here is what I've come up with so far. Please excuse the awful color scheme - it's just to delineate the divs:
$("#right-sidebar-slider").click(function() {
$('#right-sidebar-content').hide('slide', {
direction: 'right'
}, 300);
$("#topic-container").animate({
width: "75%"
}, {
duration: 600,
specialEasing: {
width: 'linear'
}
});
});
$("#left-sidebar-slider").click(function() {
$('#left-sidebar-content').hide('slide', {
direction: 'left'
}, 300);
$("#topic-container").animate({
width: "77%"
}, {
duration: 600,
specialEasing: {
width: 'linear'
}
});
});
#left-sidebar-slider {
float: left;
width: 3%;
padding-top: 20px;
background-color: green;
min-height: 600px;
}
#left-sidebar-content {
float: left;
width: 19%;
padding-top: 20px;
background-color: pink;
min-height: 600px;
}
#topic-container {
float: left;
min-width: 58%;
min-height: 600px;
padding-top: 20px;
background-color: red;
}
#right-sidebar-slider {
float: left;
width: 3%;
padding-top: 20px;
background-color: green;
min-height: 600px;
}
#right-sidebar-content {
float: left;
width: 17%;
padding-top: 20px;
background-color: pink;
min-height: 600px;
}
.header {
display: flex;
align-items: center;
}
.header .logo {
background: url("logo-onlinehelp.png") no-repeat;
width: 60%;
height: 25px;
border: 1px solid green;
margin-left: 15px;
}
.header .search-input {
border: 2px solid blue;
width: 40%;
margin-left: 25px;
}
footer {
clear: left;
border-top: 1px solid #cccccc;
width: 100%;
height: 40px;
bottom: 0;
position: relative;
background-color: gray;
}
<!doctype html>
<html lang="en">
<head>
<title></title>
<link href="favicon.ico" rel="icon" type="image/x-icon" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="vertex.js"></script>
<script src="dhtml_toc.js"></script>
<script src="dhtml_search.js"></script>
<link rel="stylesheet" type="text/css" href="stylesheet_vertex.css">
<script type="text/javascript" src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<!-- need for slider effect -->
</head>
<body>
<div class="header" style="height: 70px; background-color: gray">
<div class="logo">
</div>
<div class="search-input">
<form action="#">
<input type="text" name="search-input" value="Search available topics..." size="70">
<input type="submit" value="Submit">
</form>
</div>
</div>
<div id="left-sidebar-content">
Table of Contents...
</div>
<div id="left-sidebar-slider">
<<
</div>
<div id="topic-container">
Topic here...
</div>
<div id="right-sidebar-slider">
>>
</div>
<div id="right-sidebar-content">
Feedback form here...
</div>
<footer>
This is our footer text.
</footer>
</body>
</html>
So I have two questions:
1. In terms of overall page structure/approach - wHat is the best approach to building something like this?
What is the best approach to replicating the sliding divs? I don't need them to animate, though that would be nice. I just need the user to be able to fill the viewport with the center topic div content.
All of the actual content will come from a CMS. This single page I'm creating is just a template that the CMS (a proprietary one) will use to then insert the content, table of contents, etc. into the html.
Your approach is not far off, but I have a couple of suggestions:
CSS flexbox instead of floats to setup the three column layout. (A Complete Guide to Flexbox)
Use CSS transitions instead of javascript to add the sliding effect. (Using CSS transitions)
Let the click of a button add/remove a class to the sidebar elements, so you do not need to have presentational informasjon in your javascript
Codepen: https://codepen.io/anon/pen/XqaGEg
HTML:
<button class="sidebar-left-toggle">
<<
</button>
<button class="sidebar-right-toggle">
>>
</button>
<div class="container">
<div class="sidebar-left">sidebar-left</div>
<div class="content">content</div>
<div class="sidebar-right">sidebar-right</div>
</div>
CSS:
.container {
display: flex;
height: 200px;
transition: width 0.3s;
}
.sidebar-left,
.sidebar-right {
background: #ccc;
width: 200px;
transition: width 0.3s;
}
.sidebar-collapsed {
width: 0;
overflow: hidden;
}
.content {
background: #eee;
flex-grow: 1;
}
Javascript:
const leftToggle = document.querySelector('.sidebar-left-toggle');
const rightToggle = document.querySelector('.sidebar-right-toggle');
const leftSidebar = document.querySelector('.sidebar-left');
const rightSidebar = document.querySelector('.sidebar-right');
leftToggle.addEventListener('click', e => {
leftSidebar.classList.toggle('sidebar-collapsed');
});
rightToggle.addEventListener('click', e => {
rightSidebar.classList.toggle('sidebar-collapsed');
});

Categories

Resources