Bootstrap Flex - Prevent Child Items from Stretching Container - javascript

I'm trying to establish a layout where everything can be viewed without scrolling. Any panels that needs more space should be scrollable. In the example below, instead of main-left being stretched, I would like it so that the contents of main-left is srollable and not stretch the entire row.
for (let i = 0; i < 20; i++) {
$("#main-left").append("<div>" + i + "</div>");
}
html,
body {
height: 100%;
max-height: 100vh;
}
#main {
background-color: cyan;
min-height: 100vh;
}
#main-right {
background-color: red;
}
#main-left {
background-color: pink;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container-fluid d-flex flex-column" id="main">
<nav class="navbar">
<div class="container-fluid">
<div class="navbar-header">
<d class="navbar-brand">Header</d>
</div>
</div>
</nav>
<div class="row d-flex flex-grow-1 " id="main-row">
<div class="col-5 d-flex flex-column" id="main-left">
</div>
<div class="col-2" id="main-center">
</div>
<div class="col-5" id="main-right">
</div>
</div>
</div>

In order for an element to scroll, it must:
Have an explicit height
Have enough content to overflow that explicit height
Have overflow: auto or scroll declared
The following CSS rule will target all direct children of your #main-row and prevent them from stretching your container, allowing scroll:
#main-row > * {
max-height: 100%;
overflow: auto;
}
for (let i = 0; i < 30; i++) {
$("#main-left").append("<div>" + i + "</div>");
}
#main {
background-color: cyan;
max-height: 100vh;
overflow: hidden;
}
#main-row>* {
max-height: 100vh;
overflow: auto;
}
#main-right {
background-color: red;
}
#main-left {
background-color: pink;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<div class="container-fluid d-flex flex-column" id="main">
<nav class="navbar">
<div class="container-fluid">
<div class="navbar-header">
<d class="navbar-brand">Header</d>
</div>
</div>
</nav>
<div class="row d-flex flex-grow-1 " id="main-row">
<div class="col-5 d-flex flex-column" id="main-left">
left
</div>
<div class="col-2" id="main-center">
center
</div>
<div class="col-5" id="main-right">
right
</div>
</div>
</div>

Related

Creating Slider for showing multiple images

I am creating a slider using HTML, javascript, and CSS.
The problem I have it showing only the first two images (li) and not sliding to the other (li) elements.
I have the code of HTML as following:
<section id="cliens" class="cliens section-bg">
<div class="container">
<ul id="slider">
<li>
<div class="row" data-aos="zoom-in">
<div class="col-lg-2 col-md-4 col-6 d-flex align-items-center justify-content-center">
<img src="assets/img/clients/client-1.png" class="img-fluid" alt="">
</div>
<div class="col-lg-2 col-md-4 col-6 d-flex align-items-center justify-content-center">
<img src="assets/img/clients/client-2.png" class="img-fluid" alt="">
</div>
</div>
</li>
<li>
<div class="row" data-aos="zoom-in">
<div class="col-lg-2 col-md-4 col-6 d-flex align-items-center justify-content-center">
<img src="assets/img/clients/client-1.png" class="img-fluid" alt="">
</div>
<div class="col-lg-2 col-md-4 col-6 d-flex align-items-center justify-content-center">
<img src="assets/img/clients/client-2.png" class="img-fluid" alt="">
</div>
</div>
</li>
<li>
<div class="row" data-aos="zoom-in">
<div class="col-lg-2 col-md-4 col-6 d-flex align-items-center justify-content-center">
<img src="assets/img/clients/client-1.png" class="img-fluid" alt="">
</div>
<div class="col-lg-2 col-md-4 col-6 d-flex align-items-center justify-content-center">
<img src="assets/img/clients/client-2.png" class="img-fluid" alt="">
</div>
</div>
</li>
</ul>
</div>
</section>
and the javascript code as following:
<script>
// Slide every slideDelay seconds
const slideDelay = 5000;
const dynamicSlider = document.getElementById("slider").value;
var curSlide = 0;
window.setInterval(()=>{
curSlide++;
if (curSlide === dynamicSlider.childElementCount) {
curSlide = 0;
}
// Actual slide
dynamicSlider.firstElementChild.style.setProperty("margin-left", "-" + curSlide + "00%");
}, slideDelay);
</script>
and the CSS as following:
<style>
#slider {
width: 100%;
height: 100%;
margin: 0 auto;
border: 10px solid transparent;
padding: 0px;
z-index: 100;
overflow: hidden;
white-space: nowrap;
box-sizing: border-box;
}
#slider > li {
width: 100%;
height: 100%;
position: relative;
display: inline-block;
overflow: hidden;
font-size: 15px;
font-size: initial;
line-height: normal;
transition: all 0.5s cubic-bezier(0.4, 1.3, 0.65, 1); /* Slide css animation */
background-size: cover;
vertical-align: top;
box-sizing: border-box;
white-space: normal;
}
</style>
1: You are trying to get the value of slider but slider does not have any value.
2: You are trying to define a non css value in line 14 (margin-left -000% are trying to do what?)
3: I think you missed up some lines of code, cause this code even runs...
I know what you want to do, but you need to specify a higher z-index for ul and lowers for li then make a "animation" with the li changing its positions.
I made a very simple slider without any animation, you can use it in your code if you want.
<!DOCTYPE html>
<html>
<head>
<style>
#img
{
transition: linear 2s;
width: 500px;
height: 500px;
}
</style>
<title>Page Title</title>
</head>
<body>
<img src="https://images.unsplash.com/photo-1448375240586-882707db888b?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxzZWFyY2h8MXx8Zm9yZXN0fGVufDB8fDB8&auto=format&fit=crop&w=600&q=60" id="img">
<script>
var counter = 0;
var t;
window.onload = function() {setInterval(change, 5000);}
function change()
{
var imgs = ['https://images.unsplash.com/photo-1473448912268-2022ce9509d8?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1025&q=80', 'https://images.unsplash.com/photo-1519821172144-4f87d85de2a1?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1231&q=80', 'https://images.unsplash.com/photo-1448375240586-882707db888b?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxzZWFyY2h8MXx8Zm9yZXN0fGVufDB8fDB8&auto=format&fit=crop&w=600&q=60'];
if(counter === 3)
{ counter = 0; }
else
{
document.getElementById('img').src = imgs[0 + counter];
counter++;
}
}
</script>
</body>
</html>
If you fix these errors I can give you the entire answer.
Hope I helped!

Prevent div scrolling up when bumped by div below it?

I asked a similar question yesterday but explained it poorly, and didn't specify my desire for a pure-CSS solution, which I think should be possible, so I'm trying again.
Basically, I have an issue where I have a div of scrollable messages and an input field below it. When I click a button, I would like the input field to be bumped up 100 pixels, without having the div of messages scroll as well.
Here is a fiddle that demonstrates the problem in its entirety
As you can see, when you click the "add margin" button, the messages div scrolls up as well. I would like it to stay where it was. Similarly, if you are slightly scrolled up so you can only see the second to last message, clicking the button should similarly retain that position upon click.
The interesting thing is that this behavior is "sometimes" preserved. For example, in some circumstances (which I can't quite deduce) the scroll position is retained. I would just like it to consistently behave as such.
window.onload = function(e) {
document.querySelector(".messages").scrollTop = 10000;
};
function test() {
document.querySelector(".send-message").classList.toggle("some-margin");
}
.container {
width: 400px;
height: 300px;
border: 1px solid #333;
display: flex;
flex-direction: column;
}
.messages {
overflow-y: auto;
height: 100%;
}
.send-message {
width: 100%;
display: flex;
flex-direction: column;
}
.some-margin {
margin-bottom: 100px;
}
<div class="container">
<div class="messages">
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
</div>
<div class="send-message">
<input />
</div>
</div>
<button onclick="test()">add margin</button>
This is a funny solution that you might like.
What we know about the div that it preserve only the top position of the scrollbar so if the height changed due to any reason the scrollbar will remain the same and this is what causes your issue.
As workaround you can flip the .messages 180 degree using transform: rotate(180deg) scaleX(-1); and flip back the .message to cancel flipping the content then the div will maintain the bottom scrollbar (which is top) automatically.
function test() {
document.querySelector(".send-message").classList.toggle("some-margin")
}
.container {
width: 400px;
height: 300px;
border: 1px solid #333;
display: flex;
flex-direction: column;
}
.messages {
overflow-y: auto;
height: 100%;
transform: rotate(180deg) scaleX(-1);
}
.message
{
transform: rotate(180deg) scaleX(-1);
}
.send-message {
width: 100%;
display: flex;
flex-direction: column;
}
.some-margin {
margin-bottom: 100px;
}
<div class="container">
<div class="messages">
<div class="message">hello1</div>
<div class="message">hello2</div>
<div class="message">hello3</div>
<div class="message">hello4</div>
<div class="message">hello5</div>
<div class="message">hello6</div>
<div class="message">hello7</div>
<div class="message">hello8</div>
<div class="message">hello9</div>
<div class="message">hello10</div>
<div class="message">hello11</div>
<div class="message">hello12</div>
<div class="message">hello13</div>
<div class="message">hello14</div>
<div class="message">hello15</div>
<div class="message">hello16</div>
<div class="message">hello17</div>
<div class="message">hello18</div>
<div class="message">hello19</div>
<div class="message">hello20</div>
</div>
<div class="send-message">
<input />
</div>
</div>
<button onclick="test()">add margin</button>
The normal behavior of the scrollbar it to be on the top, so when you set it to the bottom on page load, you have to maintain it your self because when ever the below content pushed it then div scroll will move to the top.
So I have two solutions for you:
Reverse the messages inside the messages div so the last message will be the first so the scroll will always be at the top.
I created a javascript function to scroll to the bottom of any element so you just call it whenever you want to scroll to the bottom.
function scrollbottom(e)
{
e.scrollTop = e.clientHeight;
}
Check the snippet
var elem = document.querySelector(".messages");
window.onload = function(e){
scrollbottom(elem);
}
function test() {
document.querySelector(".send-message").classList.toggle("some-margin");
scrollbottom(elem);
}
function scrollbottom(e)
{
e.scrollTop = e.clientHeight;
}
.container {
width: 400px;
height: 300px;
border: 1px solid #333;
display: flex;
flex-direction: column;
}
.messages {
overflow-y: auto;
height: 100%;
}
.send-message {
width: 100%;
display: flex;
flex-direction: column;
}
.some-margin {
margin-bottom: 100px;
}
<div class="container">
<div class="messages">
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
</div>
<div class="send-message">
<input />
</div>
</div>
<button onclick="test()">add margin</button>
You can do it the other way around, by giving the height to the .messages instead of giving it to the .container in this case it will not affect the messages div but if you are giving it to the .container it will push your div because the margin is inside the main div which have a height.
Check this snippet
function test() {
document.querySelector(".send-message").classList.toggle("some-margin");
}
.container {
width: 400px;
border: 1px solid #333;
display: flex;
flex-direction: column;
}
.messages {
height: 300px;
overflow-y: auto;
}
.send-message {
width: 100%;
display: flex;
flex-direction: column;
}
.some-margin {
margin-bottom: 50px;
}
<div class="container">
<div class="messages">
<div class="message">hello1</div>
<div class="message">hello2</div>
<div class="message">hello3</div>
<div class="message">hello4</div>
<div class="message">hello5</div>
<div class="message">hello6</div>
<div class="message">hello7</div>
<div class="message">hello8</div>
<div class="message">hello9</div>
<div class="message">hello10</div>
<div class="message">hello11</div>
<div class="message">hello12</div>
<div class="message">hello13</div>
<div class="message">hello14</div>
<div class="message">hello15</div>
<div class="message">hello16</div>
<div class="message">hello17</div>
<div class="message">hello18</div>
<div class="message">hello19</div>
<div class="message">hello20</div>
</div>
<div class="send-message">
<input />
</div>
</div>
<button onclick="test()">add margin</button>
The simple workaround is to set the previous scrollTop on toggle. Here I am using dataset to store previous scrollTop value, you can use variable either.
window.onload = function(e) {
document.querySelector(".messages").scrollTop = 10000;
}
function test() {
let state = document.querySelector(".send-message").classList.toggle("some-margin")
let div = document.querySelector(".messages");
if (state) {
div.dataset.top = div.scrollTop;
div.scrollTop += 100 // same as margin-bottom of .some-margin
} else {
div.scrollTop = div.dataset.top;
}
}
.container {
width: 400px;
height: 300px;
border: 1px solid #333;
display: flex;
flex-direction: column;
}
.messages {
overflow-y: auto;
height: 100%;
}
.send-message {
width: 100%;
display: flex;
flex-direction: column;
}
.some-margin {
margin-bottom: 100px;
}
<div class="container">
<div class="messages">
<div class="message">hello1</div>
<div class="message">hello2</div>
<div class="message">hello3</div>
<div class="message">hello4</div>
<div class="message">hello5</div>
<div class="message">hello6</div>
<div class="message">hello7</div>
<div class="message">hello8</div>
<div class="message">hello9</div>
<div class="message">hello10</div>
<div class="message">hello11</div>
<div class="message">hello12</div>
<div class="message">hello13</div>
<div class="message">hello14</div>
<div class="message">hello15</div>
<div class="message">hello16</div>
<div class="message">hello17</div>
<div class="message">hello18</div>
<div class="message">hello19</div>
<div class="message">hello20</div>
</div>
<div class="send-message">
<input />
</div>
</div>
<button onclick="test()">add margin</button>
I mean, the following is a CSS only solution that solves exactly your example:
.some-margin{margin-bottom:100px;}
.messages{margin-top:-100px;}
but I don't think it'll help you with your original problem of the virtual keyboard. But perhaps this can inspire someone else to a solution.
The main problem seems to be that the scrollbar is already doing exactly what you want:
Maintaining its position so the most recently read content is visible.
Except the scrollbar decides that you wanted to see the TOP of the currently visible content, not the bottom. (It's easier to see if you use numbers: https://jsfiddle.net/1co3x48n/ )
If you're willing to use javascript, there's all sorts of answers:
https://www.google.com/search?q=scrollbar+always+on+bottom+css+site:stackoverflow.com
Honestly, the fact that you can go through ~3+ pages of this and find only Javascript answers tells me that you're not going to find a CSS-only answer, certainly not one that's widely browser-compatible.
Create a container like in above examples, but then just alter the CSS when you start typing.
I dont set the scrollbar position, just move the whole message container upwards. So whatever your scrollposition might be, will stay the same. At least downwards, of course you will not be able to see the lines at the top.
You should be able to tweak the css to your needs. You could even go without JS if you use :focus or slightly different CSS setup, be creative :)
function activate(){
document.querySelector("#container").classList.toggle("active");
}
#container{
position:relative;
width:300px;
height:100vh;
max-height:230px;
overflow:hidden;
}
#messages{
position:absolute;
bottom:30px;
overflow:auto;
height:200px;
width:100%;
background:#eee;
}
#container.active #messages {
bottom:100px;
}
#send-message{
position:absolute;
border:1px solid #ccc;
bottom:0;
height:28px;
}
#container.active #send-message{
height:100px;
}
<div id="container">
<div id="messages">
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
</div>
<div id="send-message">
<input id="newmessage" onclick="activate()" type="text" />
</div>
</div>
you must add document.querySelector(".messages").scrollTop = 10000; to test function when add margin then scrollTop go to end
in load you set scrolltop and when you add margin or remove margin scrolltop didn't set again
change you script to like this
<script>
window.onload = function(e){
document.querySelector(".messages").scrollTop = 10000;
}
function test() {
document.querySelector(".send-message").classList.toggle("some-margin")
document.querySelector(".messages").scrollTop = 10000;
}
</script>
There seems to be a problem with the js toggle function. I've changed it to a simple hide & show. Also I've added a width on the input tag. You also need to add a position: absolute on the send-message div and bottom: 0 so it stays at the bottom. then place position: relative on the container so that the send message div stays within the container. This means that the message container won't affect the messages themselves and push them up.
window.onload = function(e) {
document.querySelector(".messages").scrollTop = 10000;
};
function test() {
var x = document.querySelector(".send-message");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
.container {
width: 400px;
height: 300px;
border: 1px solid #333;
display: flex;
flex-direction: column;
position: relative;
}
.messages {
overflow-y: auto;
height: 100%;
}
.send-message {
width: 100%;
display: flex;
flex-direction: column;
position: absolute;
bottom: 0;
}
.send-message input {
width:100%;
}
.some-margin {
margin-bottom: 100px;
}
<div class="container">
<div class="messages">
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">test</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
</div>
<div class="send-message">
<input />
</div>
</div>
<button onclick="test()">add margin</button>
None of the solutions provided really seem to work unfortunately. The problem with using onFocus for a textbox is that it won't apply if the textbox already has focus. The closest solution I've come up with so far is this:
componentDidMount() {
this.screenHeight = window.innerHeight;
let chatElem = document.querySelector(".conversations-chat");
window.addEventListener('resize', () => {
let diff = this.screenHeight - window.innerHeight;
chatElem.scrollTop += diff;
this.screenHeight = window.innerHeight;
});
}
However, this only seems to sometimes work. It works 100% of the time when clicking the textbox, but for some reason when closing the virtual keyboard it only works if it was scrolled up enough. Otherwise it resets to the same position every time (near the bottom, but not quite the bottom).
Not sure what's causing that. Will have to investigate more tomorrow I suppose. This is the closest one thus far though.
This could be one more approach that we can explore. If we don't want to play with scroll position and if it is ok if we shrink messages container without loosing usability. Then we can try something like below. For better understanding view the output in full page.
window.onload = function(e) {
document.querySelector(".messages").scrollTop = 10000;
};
function test() {
document.querySelector(".send-message").classList.toggle("some-margin");
document.querySelector(".messages").classList.toggle("scale");
}
.container {
width: 400px;
height: 300px;
border: 1px solid #333;
position: relative;
}
.messages {
position: absolute;
top: 0px;
left: 0px;
overflow-y: auto;
/* leave 1.4 rem space for input */
height: calc(300px - 1.4rem);
width: 100%;
}
.scale {
/*half of the 100 margin */
top: -50px;
/* scale = (totalHeight - 100px)/totalHeight */
transform: scaleY(0.64);
}
.send-message {
position: absolute;
bottom: 0;
width: 100%;
overflow: hidden;
}
.some-margin {
margin-bottom: 100px;
}
<div class="container">
<div class="messages">
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello4</div>
<div class="message">hello3</div>
<div class="message">hello2</div>
<div class="message">hello1</div>
</div>
<div class="send-message">
<input style="width:100%" />
</div>
</div>
<button onclick="test()">add margin</button>
A pure imperfect CSS approach that I can come up with is the following:
window.onload = function(e){
document.querySelector(".messages").scrollTop = 10000;
}
document.querySelector('button').addEventListener('click', test)
function test() {
document.querySelector(".send-message").classList.toggle("some-margin")
document.querySelector('.wrapper').classList.toggle('wrapper--transformed')
}
.container {
width: 400px;
height: 300px;
border: 1px solid #333;
display: flex;
flex-direction: column;
}
.messages {
position: relative;
overflow-y: auto;
height: 100%;
}
.wrapper {
display: block;
}
.wrapper--transformed {
transform: translateY(-100px);
margin-bottom: -100px;
}
.send-message {
width: 100%;
display: flex;
flex-direction: column;
}
.some-margin {
margin-bottom: 100px;
}
<div class="container">
<div class="messages">
<div class = "wrapper">
<div class="message">hello1</div>
<div class="message">hello2</div>
<div class="message">hello3</div>
<div class="message">hello4</div>
<div class="message">hello5</div>
<div class="message">hello6</div>
<div class="message">hello7</div>
<div class="message">hello8</div>
<div class="message">hello9</div>
<div class="message">hello1</div>
<div class="message">hello2</div>
<div class="message">hello3</div>
<div class="message">hello4</div>
<div class="message">hello5</div>
<div class="message">hello6</div>
<div class="message">hello7</div>
<div class="message">hello8</div>
<div class="message">hello9</div>
<div class="message">hello1</div>
<div class="message">hello2</div>
</div>
</div>
<div class="send-message">
<input />
</div>
</div>
<button>add margin</button>
The topmost section has a little problem when margin is there. The trick here is using negative margin and using translate to "scroll up" (not really a scroll, just an illusion) the wrapper div.
It can very simply be addressed with anchor names. Look at the JS fiddle at https://jsfiddle.net/gvbz93sx/
HTML Change
<a name="bottom"></a>
JS Change
document.location.hash = "#bottom";

Define a responsive square grid

I need help doing a CSS task. I have done the following setup:
function ind2sub(siz,ind){
rowsub = Math.floor(ind/siz[1])
colsub = ind % siz[1]
return [rowsub,colsub]
}
function sub2ind(siz,rowsub,colsub){
return siz[1]*Math.floor(rowsub)+Math.floor(colsub)
}
var rows = 7
var cols = 7
for(i = 0;i<rows*cols;i++){
var probe = $('<span data-id="'+i+'" data-selected="0" class="probe" style="font-size:6px;">'+i+'</span>')
$('#mcuframe').append(probe)
}
ind = sub2ind([rows,cols],rows/2,cols/2)
$('#mcuframe .probe[data-id="' + ind +'"]').addClass("fieldselected")//.css("background-color","lightblue")
rows = 14
cols = 19
for(i = 0;i<rows*cols;i++){
var sample = $('<span data-id="'+i+'" data-selected="0" class="sample" style="font-size:6px;">'+i+'</span>')
$('#fovframe').append(sample)
}
ind = sub2ind([rows,cols],rows/2,cols/2)
$('#fovframe .sample[data-id="'+ind+'"]').addClass("fieldselected")//css("background-color","lightblue")
$('.probe,.sample').click(function(){
if($(this).hasClass('probe')){
$('.probe').removeClass('fieldselected')
$(this).addClass("fieldselected")
}
else if($(this).hasClass('sample')){
$('.sample').removeClass('fieldselected')
$(this).addClass("fieldselected")
}
});
$('#move2samplebtn').click(function () {
/*if ($('#con_mcu_tgl').prop("checked") == false) {
return
}*/
var probeidx = ind2sub([7,7], $('.probe.fieldselected').data('id'))
var sampleidx = ind2sub([14,19], $('.sample.fieldselected').data('id'))
});
#mcuframe {
display: grid;
grid-template-columns: repeat(7, 1fr);
grid-template-rows: repeat(7, 1fr);
grid-gap: 2px;
background-color: black;
border: solid 2px black;
}
#mcuframe .probe {
background-color: white;
cursor: pointer;
}
#mcuframe .probe:hover{
background-color: gray;
}
#mcuframe .probe::before {
content: "";
padding-top: 100%;
float: left;
width: 0;
height: 0;
box-sizing: content-box;
}
#fovframe {
display: grid;
grid-template-columns: repeat(19, 1fr);
grid-template-rows: repeat(14, 1fr);
grid-gap: 2px;
background-color: black;
border: solid 2px black;
}
#fovframe .sample {
background-color: white;
cursor: pointer;
}
#fovframe .sample:hover{
background-color: gray;
}
#fovframe .sample::before {
content: "";
padding-top: calc(100% / 19 * 14);
float: left;
width: 0;
height: 0;
}
.fieldselected{
background-color:lightblue !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://use.fontawesome.com/releases/v5.2.0/css/all.css" rel="stylesheet"/>
<div class="container-fluid">
<div class="row">
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-4">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Dashboard</h1>
</div>
<div class="container" style="padding: 0px; margin: 0px;">
<div class="row" style="padding: 0px; margin: 0px;">
<div class="col-lg-9">
<ul class="nav nav-tabs" role="tablist" id="controltabs">
<li class="nav-item">
<a class="nav-link" href="#movpanel" role="tab" data-toggle="tab">
<i class="fa fa-arrows-alt"></i>
</a>
</li>
</ul>
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="movpanel">
<div class="card">
<div class="card-header">
Move panel
</div>
<div class="card-body">
<div style="width: 48%; float:left">
<h4>1) Choose probe</h4>
<div id="mcuframe"></div>
</div>
<div style="width: 48%; float:right">
<h4>2) Choose sample </h4>
<div id="fovframe"></div>
</div>
<div class="clearfix"></div>
<div class="row no-gutters mt-4">
<div class="col">
<button class="btn btn-success col-12" id="move2samplebtn">
Move to chosen sample
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
This kinda works, but my problem here is primarily that the surrounding frame under 2) is not square, but also that the text breaks the surrounding container on smaller screens. Both frames under 1) and 2) should always be square and have same size regardless of windowsize(responsive design). Also, if i change the number of the grid cells either horizontally or vertically or both it should remain square under same conditions as described above. Its the boxes inside the frame which needs to change aspect ratio when the number of boxes in either direction changes. I have tried using a css grid approach as shown in the fiddle, but this is not doing the job as i expected. What am I doing wrong here since the grid does not remain square?

Make progress bars responsive

I have these progress bars which are suppose to work as ratings and they look good:
I have applied some CSS and I change their width with JavaScript by reading values from text files.
But are not responsive at all and whenever the window is resized:
HTML:
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<div class="second-part">
<div class="row">
<div class="side">
<div>5 stars</div>
</div>
<div class="middle">
<div class="bar-container">
<div class="bar11" style="width: 10% ; height: 18px; background-color: gold;"></div>
</div>
</div>
<div class="side right">
<div class="p11">150</div>
</div>
<div class="side">
<div>4 stars</div>
</div>
<div class="middle">
<div class="bar-container">
<div class="bar12" style="width: 10% ; height: 18px; background-color: gold;"></div>
</div>
</div>
<div class="side right">
<div class="p12">63</div>
</div>
<div class="side">
<div>3 stars</div>
</div>
<div class="middle">
<div class="bar-container">
<div class="bar13" style="width: 10% ; height: 18px; background-color: gold;"></div>
</div>
</div>
<div class="side right">
<div class="p13">15</div>
</div>
<div class="side">
<div>2 stars</div>
</div>
<div class="middle">
<div class="bar-container">
<div class="bar14" style="width: 10% ; height: 18px; background-color: gold;"></div>
</div>
</div>
<div class="side right">
<div class="p14">6</div>
</div>
<div class="side">
<div>1 star</div>
</div>
<div class="middle">
<div class="bar-container">
<div class="bar15" style="width: 10% ; height: 18px; background-color: gold;"></div>
</div>
</div>
<div class="side right">
<div class="p15">20</div>
</div>
</div>
</div>
CSS:
* {
box-sizing: border-box;
}
/* Three column layout */
.side {
float: left;
width: 15%;
margin-top:10px;
}
.middle {
margin-top:10px;
float: left;
width: 70%;
}
/* Place text to the right */
.right {
text-align: left;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
/* The bar container */
.bar-container {
width: 90%;
background-color: #f1f1f1;
text-align: center;
color: white;
}
/* Responsive layout - make the columns stack on top of each other instead of next to each other */
#media (max-width: 400px) {
.side, .middle {
width: 100%;
}
.right {
display: none;
}
}
JavaScript to change progress bar width:
var par1 = 4;
for(var i = 10; i < 16; i++) {
$('.p' + (i+1)).text(table[0][par1]);
$('.bar' + (i+1)).css("width", table[0][par1]);
par1++;
}
How could I make it more responsive? Thank you in advance!
I recommend using css flexbox, so the items wrap instead of overlap when the page is resized. You could use media queries with this to adjust the size of the items and container so they don't overlap/wrap. This site has a good explanation of flexbox: A Complete Guide to Flexbox.

Dynamically changing columns sizes on click

I would like to have three columns on my page, but column2 should initially have a size of column size of 0, ie col-md-0. When the user clicks on a link in the navigation bar, I would like column2 to expand to col-md-3, and column3 should shrink to adjust.
For example, this is what I would imagine my columns' html to be when the page is loaded:
<div class="container-fluid">
<div class="row no-gutter">
<div id="col1" class="col-md-1">
<vs-navbar></vs-navbar>
</div>
<div id="col2" class="col-md-0">
<router-outlet></router-outlet>
</div>
<div id="col3" class="col-md-11">
<div class="placeholder">
</div>
</div>
</div>
</div>
The navbar could be:
<nav class="navbar navbar-inverse navbar-full">
<ul class="nav nav-stacked">
<li>
<a>Home</a>
</li>
<li>
<a>Info</a>
</li>
</ul>
</nav>
When the Info link is clicked, I would like the html to transition to:
<div class="container-fluid">
<div class="row no-gutter">
<div id="col1" class="col-md-1">
<vs-navbar></vs-navbar>
</div>
<div id="col2" class="col-md-3">
<router-outlet></router-outlet>
</div>
<div id="col3" class="col-md-8">
<div class="placeholder">
</div>
</div>
</div>
</div>
I have a vague but messy idea how this could be done with some javascript, but I've seen this kind of thing on several sites so I'm looking for the clean, recommended way of doing this, especially as I'm using bootstrap.
Because you have IDs, I assume you now the exact structure of your row.
If it is so, a solution can be based on toggleClass:
$('a:contains("Info")').on('click', function(e) {
$('#col2').toggleClass('col-md-0 col-md-3')
$('#col3').toggleClass('col-md-11 col-md-8')
})
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<nav class="navbar navbar-inverse navbar-full">
<ul class="nav nav-stacked">
<li>
<a>Home</a>
</li>
<li>
<a>Info</a>
</li>
</ul>
</nav>
<div class="container-fluid">
<div class="row no-gutter">
<div id="col1" class="col-md-1">
<vs-navbar>aaaaaa</vs-navbar>
</div>
<div id="col2" class="col-md-0">
<router-outlet>bbbbbb</router-outlet>
</div>
<div id="col3" class="col-md-11">
<div class="placeholder">cccc
</div>
</div>
</div>
</div>
You can use the :target pseudo-class for this.
The :target pseudo-class is used to style an element that is the
target of an internal link in a document.
Basically you hide your column, then when the user clicks the link it will show up:
#col2{
display: none;
}
#col2:target{
display: block;
}
CODE SNIPPET:
.row {
display: flex;
}
.col {
background-color: dodgerblue;
flex: 0 0 30%;
height: 100px;
}
.col:nth-child(odd) {
background-color: gold;
}
#col2 {
display: none;
animation: open 300ms linear both;
}
#col2:target {
display: block;
}
#keyframes open {
0 {
transform: rotateX(0);
}
55% {
transform: rotateX(90deg);
}
100% {
transform: rotateX(180deg);
}
}
Trigger Col 2
<div class="row">
<div id="col1" class="col"></div>
<div id="col2" class="col"></div>
<div id="col3" class="col"></div>
</div>
EDIT:
To change between .col-md-8 and .col-md-11, you can change the width of .col-md-8when your second column is not present, using the corresponding media query for md viewport.
#media (min-width: 992px) {
#col2 + .col-md-8 {
width: 91.66666667%;
}
#col2:target + .col-md-8 {
width: 66.66666667%;
}
}
Bootstrap demo:
div[class*="col"],
div[class^="col"] {
height: 100px;
}
#col1 {
background-color: gold;
}
#col3 {
background-color: purple;
}
#col2 {
background-color: dodgerblue;
display: none;
animation: open 300ms linear both;
}
#col2:target {
display: block;
}
#media (min-width: 992px) {
#col2 + .col-md-8 {
width: 91.66666667%;
}
#col2:target + .col-md-8 {
width: 66.66666667%;
}
}
#keyframes open {
0 {
transform: rotateX(0);
}
55% {
transform: rotateX(90deg);
}
100% {
transform: rotateX(180deg);
}
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
Trigger Col 2
<div class="container-fluid">
<div class="row no-gutter">
<div id="col1" class="col-md-1">
<vs-navbar></vs-navbar>
</div>
<div id="col2" class="col-md-3">
<router-outlet></router-outlet>
</div>
<div id="col3" class="col-md-8">
<div class="placeholder">
</div>
</div>
</div>
</div>

Categories