I want to create a gallery which the images get bigger in the middle.
The ammont of images are random.
With this code, I could find the middle, but I dont know how to change the size of the Images ascendens and/or descendant.
var boxes = document.querySelectorAll(".box");
var middle = boxes[Math.round((boxes.length - 1) / 2)];
middle.style.width = "70px"
middle.style.height= "70px"
.container{
display:flex;
justify-content:center;
align-items:center;
}
.box{
width:50px;
height:50px;
background-color:black;
margin:10px;
}
<div class="container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
something like this.. you can play with the number, depending on how much bigger or smaller you want them..
var boxes = document.querySelectorAll(".box");
var middle_index = Math.round((boxes.length - 1) / 2);
for ( var i=0; i<boxes.length; i++) {
boxes[i].style.width = `${70-Math.abs(boxes.length-i*2-1)*5}px`;
boxes[i].style.height = `${70-Math.abs(boxes.length-i*2-1)*5}px`;
}
.container{
display:flex;
justify-content:center;
align-items:center;
}
.box{
width:50px;
height:50px;
background-color:black;
margin:10px;
}
<div class="container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
Same as the other answer except the size calculation is moved to CSS
const boxes = document.querySelectorAll(".box");
let middle = Math.floor((boxes.length - 1) / 2);
const reductionModifier = 4; //Reduces size diff, higher means less diff.
const marginModifier = -1; //-1 means margin will be -10px
boxes.forEach((e, i) => {
e.style.setProperty('--s', 1 - ((Math.abs(i - middle) / boxes.length) / reductionModifier));
e.style.setProperty('--m', i == middle ? 1 : marginModifier);
e.style.setProperty('--z', 1 - Math.abs(i - middle));
});
.container{
display:flex;
justify-content:center;
align-items:center;
}
.box {
border: 1px solid red;
width: calc(70px * var(--s));
height: calc(70px * var(--s));
background-color:black;
margin: calc(10px * var(--m));
z-index: calc(10 * var(--z));
}
<div class="container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
Related
This question already has answers here:
Can't scroll to top of flex item that is overflowing container
(12 answers)
Closed 1 year ago.
I have a column flexbox with width:100% and overflow-x:auto , inside this flexbox there are variable numbers of rows and each row can contain 1,2,4,8,16,... elements.
consider bellow example:
first row ---> has 1 element
second row ---> has 2 elements
third row ---> has 4 elements
forth row ---> has 8 elements
...
and elements on each row should be centered.
in my code all the left side elements will be cut off , how can I prevent this ??
const itemWidth = 300; //300px
document.querySelectorAll('.item').forEach((item) => {
item.style.width = `${itemWidth}px`;
});
document.querySelectorAll('.row').forEach((row, i) => {
row.style.width = `${
(Math.pow(2, i) + (Math.pow(2, i) - 1)) * itemWidth
}px`; //calc needed width of each row
});
.rows {
width: 100%;
overflow-x: auto;
display: flex;
flex-direction: column;
align-items: center;
}
.row {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
.item {
height: 100px;
background-color: royalblue;
margin: 20px;
}
<div class="rows">
<div class="row">
<div class="item"></div>
</div>
<div class="row">
<div class="item"></div>
<div class="item"></div>
</div>
<div class="row">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<div class="row">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</div>
For the first div. You are assigning a width of only one item. So, flex items got cut off to left. Please check the below code. Get the length of items contains a max length of a row. Assign it to all the divs. If your unable to view the below code in snippet. Check it here - https://codepen.io/kcsmastermind/pen/MWpPBrY
const itemWidth = 300; //300px
document.querySelectorAll('.item').forEach((item) => {
item.style.width = `${itemWidth}px`;
});
let rows = document.getElementsByClassName("row");
let maxNumber = 0;
for (let i=0; i < rows.length; i++) {
if (maxNumber < rows[i].childElementCount) maxNumber = rows[i].childElementCount;
};
document.querySelectorAll('.row').forEach((row, i) => {
row.style.minWidth = `${
maxNumber * itemWidth
}px`; //calc needed width of each row
});
.rows {
display: flex;
flex-direction: column;
align-content: center;
width: 100%;
overflow-x: auto;
}
.row {
display: flex;
justify-content: center;
margin-top: 20px;
}
.item {
height: 100px;
background-color: royalblue;
margin: 20px;
}
<div class="rows">
<div class="row">
<div class="item"></div>
</div>
<div class="row">
<div class="item"></div>
<div class="item"></div>
</div>
<div class="row">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<div class="row">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</div>
Here's a pure CSS solution (I took some liberties with styling to hopefully make it easier to see what's going on):
https://jsfiddle.net/5hq924uf/1/
Rather than calculating element widths via Javascript, the .rows container width is set based on its child content with this rule:
width: min-content;
This then props the page open, preventing elements from getting cut off when centered using flex.
Note that while the min-content feature seems to be well-supported in modern browsers, it's not going to work in some legacy browsers, so be aware:
https://caniuse.com/mdn-css_properties_width_min-content
I was trying to apply iScroll to my scrolling item however i dont understand the way it works.
it cuts off bottom content
it makes additional margin top for some reason
this is the code
var _scroll = new IScroll('.helper', {
mouseWheel: true,
scrollbars: true
});
div {
box-sizing:border-box;
}
.main {
width:600px;
margin:20px auto;
height:300px;
background:crimson;
border:solid 1px #000;
padding:10px;
}
.helper {
height:100%;
position:relative;
overflow:hidden;
}
.scroller {
background:cornflowerblue;
}
.box {
height:50px;
background:#ccc;
border:solid 1px #000;
margin:10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/iScroll/5.2.0/iscroll.min.js"></script>
<div class="main">
<div class="helper">
<div class="scroller">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
</div>
Maybe someone could help me with this one.
I am making an interactive puzzle where the user is supposed to change the color of particular blocks in order to make an image. In this case, I would like a pop up to appear (the pop up currently hidden) when all particular blocks are X color. I know how to trigger a 1 click pop up, but I don't know how to make it so when MULTIPLE boxes are the right color, the pop up is revealed to advance the player to the next puzzle. My sad attempt can be found at the bottom of the JS (the audio right now isn't important).
Here is my HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Block Party</title>
<link rel="stylesheet" href="gridtest.css">
</head>
<body>
<div class="boxorganization">
<div class="popup">
<div class="congrats">puzzle <br>complete!</div>
<div class="next">next</div>
</div>
<!-- 20 boxes per group MAGENTA BOXES-->
<div class="box" id="specialbox"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
<audio id="coin" src="sounds/coin.mp3"></audio>
<audio id="ding" src="sounds/ding.mp3"></audio>
<audio id="drip" src="sounds/drip.mp3"></audio>
<audio id="flick" src="sounds/flick.mp3"></audio>
<audio id="power" src="sounds/power.mp3"></audio>
<audio id="zap" src="sounds/zap.mp3"></audio>
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<script src="gridtest.js" charset="utf-8"></script>
Here is my CSS:
html{
height: 100%;
}
*, *::before, *::after{
box-sizing: border-box;
}
body{
box-sizing: border-box;
background-color: #00008B;
}
.boxorganization{
position: absolute;
width: 500px;
top: 85px;
left: 400px;
display: flex;
flex-wrap: wrap;
}
.box{
width: 50px;
height: 50px;
background: magenta;
/*margin: -.5px;*/
border: 1px solid #00008B;
}
.specialbox{
width: 50px;
height: 50px;
background: magenta;
/*margin: -.5px;*/
border: 1px solid #00008B;
}
.popup{
display: none;
position: absolute;
top: 50%;
margin-top: -250px;
left: 50%;
margin-left: -250px;
width: 500px;
height: 500px;
opacity: 0.8;
background-color: yellow;
}
.popupvisible{
position: absolute;
top: 50%;
margin-top: -250px;
left: 50%;
margin-left: -250px;
width: 500px;
height: 500px;
opacity: 0.8;
background-color: yellow;
}
.congrats{
font-family: 'Primetime';
font-size: 50px;
text-align: center;
position: absolute;
left: 25%;
top: 35%;
color: magenta;
opacity: 1;
}
.next{
font-family: 'Primetime';
font-size: 50px;
text-align: center;
position: absolute;
left: 38%;
top: 62%;
color: magenta;
opacity: 1;
}
/*~~~~~~~block colors~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
.yellow{
background: yellow;
}
.blue{
background: -webkit-linear-gradient(315deg, magenta 50%, yellow 50%);
/*background: blue;*/
}
.red{
background: -webkit-linear-gradient(45deg, magenta 50%, yellow 50%);
/*background: red;*/
}
.green{
background: -webkit-linear-gradient(135deg, magenta 50%, yellow 50%);
/*background: green;*/
}
.white{
background: -webkit-linear-gradient(225deg, magenta 50%, yellow 50%);
/*background: white;*/
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
and here is the JS:
// INDEX TITLE HOVER EFFECT
$(".title").hover(function () {
$(".title").addClass("titlehover");}, function () {
$(".title").removeClass("titlehover");
});
// INSTRUCTIONS HOVER EFFECT
$(".instructions").hover(function () {
$(".instructions").addClass("instructionshover");}, function () {
$(".instructions").removeClass("instructionshover");
});
// TITLE PAGE FADE INS
$(document).ready(function(){
$(".title").hide(0).delay(100).fadeIn(2000)
});
$(document).ready(function(){
$(".by").hide(0).delay(700).fadeIn(2000)
});
// PAGE 1 TITLE EFFECT
$(".text").hover(function () {
$(".text").addClass("texthover");}, function () {
$(".text").removeClass("texthover");
});
// BOX SOUNDS
//
// $('.box').click(function()){
// $(this).play('coin.mp3')
// });
// box color
$('.box').click(function(){
$(this).addClass(function(index,currentClass){
console.log(currentClass)
if(currentClass == 'box'){
$('#drip')[0].play()
return 'yellow'
}
if(currentClass == 'box yellow'){
$(this).removeClass('yellow')
$('#ding')[0].play()
return 'blue'
}
if(currentClass == 'box blue'){
$(this).removeClass('blue')
$('#flick')[0].play()
return 'red'
}
if(currentClass == 'box red'){
$(this).removeClass('red')
$('#drip')[0].play()
return 'green'
}
if(currentClass == 'box green'){
$(this).removeClass('green')
$('#ding')[0].play()
return 'white'
}
if(currentClass == 'box white'){
$(this).removeClass('white')
$('#flick')[0].play()
}
// ~~~~~~~~~~~~~ I would like for popupvisible to appear when ALL of the correct blocks are turned yellow or whatever color
if ('#specialbox' == 'box yellow'){
$("popup").addClass('popupvisible')
// or should it be "this" instead of popup?
})
});
When you click on a box, give it a class or something that indicates it was clicked/selected. You'll want to give all of the boxes a consistent class or something so that you can loop through all of them and check to see if they're selected or not. And if you loop through them all and they're all selected, show the popup. Otherwise, hide it. Here's a demo.
var $boxes = $('.box');
$('.box').on('click',function() {
var allSelected = true,
$popup = $('.popup');
$(this).toggleClass('selected');
$boxes.each(function() {
if (!$(this).hasClass('selected')) {
allSelected = false;
}
})
if (allSelected) {
$popup.addClass('popupvisible');
} else {
$popup.removeClass('popupvisible');
}
})
.box {
width: 50px;
height: 50px;
background: magenta;
border: 1px solid #00008B;
display: inline-block;
}
.selected {
background: purple;
}
.popup {
display: none;
}
.popupvisible {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="popup">popup</div>
The solution is to set up a click event handler on all the boxes that record that box color and check that record upon each click to know whether or not to display the popup.
Your code is too long to modify here, but here is a scaled down example that you could implement with your code:
// Get a collection of all the "cells"
var cells = document.querySelectorAll(".cell");
// Set up an array of possible colors
var colors = ["red", "green", "blue", "yellow", "orange", "gray", "aqua"];
// This is the record of which cell is what color:
var storage = {
cell0: "",
cell1: "",
cell2: "",
cell3: ""
};
// Set a click event handler on each cell
Array.prototype.slice.call(cells).forEach(function(cell, index){
cell.addEventListener("click", function(e){
// Change the cell color to a random color from the colors array
var c = Math.floor(Math.random() * colors.length);
e.target.style.backgroundColor = colors[c];
// Store cell and color:
storage["cell" + index] = c;
// Debugger test
console.clear();
console.log(storage);
// Test to make sure all cells have had an initial color set for them
var initialized = true;
for(var prop in storage){
if(storage[prop] === ""){
initialized = false;
break;
}
}
// Only check for color matches after each cell has had an initial
// color set for it (each cell has been clicked once).
if(initialized){
// Check to see if two adjacent cells have same color
if(storage.cell0 === storage.cell1 ||
storage.cell0 === storage.cell2 ||
storage.cell1 === storage.cell3 ||
storage.cell2 === storage.cell3){
alert("You win!");
}
}
});
});
.row1, .row2 { display:table-row; }
.cell {
display:table-cell;
height:50px;
width:50px;
border:1px solid black;
padding:5px;
}
<div class="row1">
<div class="cell">One</div>
<div class="cell">Two</div>
</div>
<div class="row2">
<div class="cell">Three</div>
<div class="cell">Four</div>
</div>
For Example:
HTML
console.log($('.container').width()); // 600px as we defined in css.
console.log($('.list').width()); // 600px
console.log($('.box').eq('-1').position().left + $('.box').outerWidth());
body{padding:0;margin:0;}
.container {
width: 600px;
backround:#E1BEE7;
}
.list {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height:120px;
background:#FFCDD2;
}
.box {
margin:10px;
flex-shrink:0;
flex-grow:0;
flex-basis:auto;
width: 100px;
height: 100px;
text-align:center;
line-height:100px;
background: #F44336;
color:#FFF;
font-size:2rem;
}
.result{
padding:1rem;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="container">
<div class="list">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
<div class="box">7</div>
<div class="box">8</div>
<div class="box">9</div>
<div class="box">10</div>
</div>
</div>
There is 10 boxes, and each box with 100px width, the actual width of element .list should be 1000px not 600px.
I tried to use the following method to get actual width of list: The left position of last child element and its outerWidth
console.log($('.box').eq('-1').position().left + $('.box').outerWidth());
What I want to know: is there a better method to get actual width of this kind of flexbox element? some better built-in javascript or jquery method exists for this?
What I need is just el.scrollWidth.
Probably more code than you wanted, but you could just sum the width of the elements inside the div, using javascript with jQuery like this:
var totalWidth = 0;
$('.box').each(function() {
totalWidth += $(this).width();
});
$('#msg').html(
"<p>totalWidth: " + totalWidth + "</p>"
);
with a live example: https://jsfiddle.net/yeeqkd2e/4/
or without jQuery
var totalWidth = 0;
var cont = document.getElementsByClassName('box');
for (var i = 0, len = cont.length; i < len; i++) {
totalWidth += cont[i].offsetWidth;
}
document.getElementById('msg').innerHTML = "<p>totalWidth: " + totalWidth + "</p>";
Native Javascript: https://jsfiddle.net/yeeqkd2e/6/
As you've discovered, scrollWidth will provide you the dimension you're looking for. The reason that outerWidth isn't giving you the total width of the internal elements is that your .list element is actually 600px wide. The additional content is overflowing its parent, allowing it to display despite being outside of the .list.
You can test this by changing the overflow property to hidden on .list:
body{ padding:0; margin:0; }
.container {
width: 600px;
}
.list {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 120px;
background: #FFCDD2;
overflow: hidden;
}
.box {
margin:10px;
flex-shrink:0;
flex-grow:0;
flex-basis:auto;
width: 100px;
height: 100px;
text-align:center;
line-height:100px;
background: #F44336;
color:#FFF;
font-size:2rem;
}
.result{
padding:1rem;
}
<div class="container">
<div class="list">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
<div class="box">7</div>
<div class="box">8</div>
<div class="box">9</div>
<div class="box">10</div>
</div>
</div>
Note that when you run this, the .list element clips the remaining boxes.
Hopefully this helps you understand what is going on in addition to solving the problem for you. Cheers!
I am building a website with content in small divs. They are all floating left so basically it's all tiled. I want a banner every third row. How many content divs are visible depends on the users screen width. I had a solution in JavaScript, but IE doesn't like that.
More graphic: this is what I want:
and on a wider screen things should look like this:
This is what I came up with:
Preview: http://jsfiddle.net/Yqy9B/5/embedded/result/
<div class="row clear">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<div class="row clear">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<div class="advert">
Advertisement
</div>
.row {
height:80px; /*height = 10px margin(top/bottom) + 60px height of .box */
overflow: hidden;
}
.box {
width:160px;
height:60px;
float:left;
background:#999;
margin:10px;
display:inline;
}
.advert {
width:485px;
height:60px;
margin:10px auto;
background:red;
text-align:center;
line-height:60px;
}
.clear:before, .clear:after { content:""; display:table; }
.clear:after { clear:both; }
.clear { zoom:1; } /* For IE 6/7 (trigger hasLayout) */
Is that what you are talking about?
http://jsfiddle.net/Yqy9B/5/
Update:
For the overlapping issue in Chrome and Safari, I've added some code that will add some padding for those browsers, as I could not find a more elegant cross-browser solution. To see the version with the additional code, see http://jsfiddle.net/Yqy9B/16/. I've also updated the code below.
Using a combination of clear: and float: properties in CSS, we can space the advertisements down one side and the content down the other. This will allow for the content to flow around the advertisements, which will keep the ads in the same spot on resize, but flow the content boxes below it.
Here's an example: http://jsfiddle.net/cjyoung1/Yqy9B/10/ (update: new example to address overlap: http://jsfiddle.net/Yqy9B/16/)
(Note: I left the spacer as red to show how it works, you can change it to your background color or transparent - but needs to be at least 1px wide to work properly in some browsers)
The CSS:
.box {
width:160px;
height:60px;
margin:10px;
background:#999;
display:inline-block;
}
.advert {
width:100%;
height:60px;
margin:10px auto;
background:red;
text-align:center;
line-height:60px;
display:block;
float:right;
clear:right;
}
.spacer {
float:right;
clear: right;
height: 250px;
width: 1px;
background: #f00;
}
/* **Below are the updates to fix the overlap in other browsers** */
/* fix webkit overlap */
#media screen and (-webkit-min-device-pixel-ratio:0) {
.advert{
margin-top:80px;
}
.spacer{
margin-bottom:-80px;
}
}
/* fix IE6 overlap */
* html .advert {
margin-top: 40px;
}
The HTML:
<!-- floating to right -->
<span class="spacer"></span>
<span class="advert">Advertisement</span>
<span class="spacer"></span>
<span class="advert">Advertisement</span>
<!-- floating to left -->
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
<div class="box">7</div>
<div class="box">8</div>
<div class="box">9</div>
<div class="box">10</div>
<div class="box">11</div>
<div class="box">12</div>
<div class="box">14</div>
<div class="box">15</div>
<div class="box">16</div>
<div class="box">17</div>
<div class="box">18</div>
<div class="box">19</div>
<div class="box">20</div>
<div class="box">21</div>
<div class="box">22</div>
<div class="box">23</div>
<div class="box">24</div>
<div class="box">25</div>