CSS spacing issue with flex display - css

I am new to CSS and not quite sure how to do spacing. Currently I have tried to center 5 wheels on the page like this:
The CSS is
body{
padding: 0px;
margin: 0px;
}
#wheels{
display: flex;
margin: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
align-items: stretch;
width: 100%
}
#wheel1, #wheel2, #wheel3, #wheel4, #wheel5, canvas{
flex-grow: 1;
margin: 0;
padding: 0;
}
canvas{
width: 100%;
}
I already have margin 0 and padding 0. I need to reduce the spacing between the wheels so that they will display bigger. Not sure about how to do this. Any help is appreciated.
EDITED:
The program is based on javascript. It is related to my other issue. But we were not able to do the spacing properly.
Complete code:
<html>
<head>
<style>
body{
padding: 0px;
margin: 0px;
}
#wheels{
display: flex;
margin: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
align-items: stretch;
width: 100%
}
#wheel1, #wheel2, #wheel3, #wheel4, #wheel5, canvas{
flex-grow: 1;
margin: 0;
padding: 0;
}
canvas{
width: 100%;
}
</style>
<script src = "phaser.min.js"></script>
<script>
// the game itself
var game;
var gameOptions = {
// slices (prizes) placed in the wheel
slices: 8,
// prize names, starting from 12 o'clock going clockwise
slicePrizes: ["A KEY!!!", "50 STARS", "500 STARS", "BAD LUCK!!!", "200 STARS", "100 STARS", "150 STARS", "BAD LUCK!!!"],
// wheel rotation duration, in milliseconds
rotationTime: 3000
}
var gameConfig;
// once the window loads...
window.onload = function () {
gameConfig = {
type: Phaser.CANVAS,
parent: 'wheel1',
width: 600,
height: 600,
backgroundColor: 0xffffff,
scene: [playGame]
};
var game = new Phaser.Game(gameConfig);
game.scene.start('PlayGame', { degrees: 50 });
gameConfig = {
type: Phaser.CANVAS,
parent: 'wheel2',
width: 600,
height: 600,
backgroundColor: 0xffffff,
scene: [playGame]
};
var game2 = new Phaser.Game(gameConfig);
game2.scene.start('PlayGame', { degrees:100 });
gameConfig = {
type: Phaser.CANVAS,
parent: 'wheel3',
width: 600,
height: 600,
backgroundColor: 0xffffff,
scene: [playGame]
};
var game3 = new Phaser.Game(gameConfig);
game3.scene.start('PlayGame', { degrees: 150 });
gameConfig = {
type: Phaser.CANVAS,
parent: 'wheel4',
width: 600,
height: 600,
backgroundColor: 0xffffff,
scene: [playGame]
};
var game4 = new Phaser.Game(gameConfig);
game4.scene.start('PlayGame', { degrees: 250 });
gameConfig = {
type: Phaser.CANVAS,
parent: 'wheel5',
width: 600,
height: 600,
backgroundColor: 0xffffff,
scene: [playGame]
};
var game5 = new Phaser.Game(gameConfig);
game5.scene.start('PlayGame', { degrees: 300 });
}
// PlayGame scene
class playGame extends Phaser.Scene {
// constructor
constructor() {
super({ key: "PlayGame" });
}
// method to be executed when the scene preloads
preload() {
//loading assets
this.load.image("wheel", "wheel.png");
this.load.image("pin", "pin.png");
}
// method to be executed once the scene has been created
create(data) {
// adding the wheel in the middle of the canvas
this.wheel = this.add.sprite(gameConfig.width / 2, gameConfig.height / 2, "wheel");
// adding the pin in the middle of the canvas
this.pin = this.add.sprite(gameConfig.width / 2, gameConfig.height / 2, "pin");
// adding the text field
this.prizeText = this.add.text(gameConfig.width / 2, gameConfig.height - 20, "Spin the wheel", {
font: "bold 32px Arial",
align: "center",
color: "black"
});
// center the text
this.prizeText.setOrigin(0.5);
// the game has just started = we can spin the wheel
this.canSpin = true;
//this.input.on("pointerdown", this.spinWheel, this);
this.spinWheel(data.degrees);
}
// function to spin the wheel
spinWheel(degrees) {
// can we spin the wheel?
if (this.canSpin) {
// resetting text field
this.prizeText.setText("");
// the wheel will spin round from 2 to 4 times. This is just coreography
var rounds = Phaser.Math.Between(8, 10);
// var degrees = Phaser.Math.Between(0, 360);
var prize = gameOptions.slices - 1 - Math.floor(degrees / (360 / gameOptions.slices));
// now the wheel cannot spin because it's already spinning
this.canSpin = false;
// animation tweeen for the spin: duration 3s, will rotate by (360 * rounds + degrees) degrees
// the quadratic easing will simulate friction
this.tweens.add({
// adding the wheel to tween targets
targets: [this.wheel],
// angle destination
angle: 360 * rounds + degrees,
// tween duration
duration: gameOptions.rotationTime,
// tween easing
ease: "Cubic.easeOut",
// callback scope
callbackScope: this,
// function to be executed once the tween has been completed
onComplete: function (tween) {
// displaying prize text
this.prizeText.setText(gameOptions.slicePrizes[prize]);
// player can spin again
this.canSpin = true;
}
});
}
}
}
</script>
</head>
<body>
<div id="wheels">
<div id="wheel1"></div>
<div id="wheel2"></div>
<div id="wheel3"></div>
<div id="wheel4"></div>
<div id="wheel5"></div>
</div>
</body>
</html>

Ok so I checked your code, the issue here is not the CSS, but it's that the spacing were determined by the width and height of the gameConfig, since the image size is 458px the size of the image inside of the canvas will be 458/600px, thus causes the spacing. What you could do is, change the 600px width to smaller value (no need to change the height though), e.g. 500px will make the image size 458/500px which will leave a 42px margin around the wheel. What you could do though, change the width from 600 to just 458 (size of the wheel image), then use CSS for the spacings.
By the way I could not reproduce your code because it seems like phaser needs the assets to be loaded locally and I couldn't add those images to be the same origin as stackoverflow domain, so I will just post code here:
Javascript:
// the game itself
var game;
var gameOptions = {
// slices (prizes) placed in the wheel
slices: 8,
// prize names, starting from 12 o'clock going clockwise
slicePrizes: ["A KEY!!!", "50 STARS", "500 STARS", "BAD LUCK!!!", "200 STARS", "100 STARS", "150 STARS", "BAD LUCK!!!"],
// wheel rotation duration, in milliseconds
rotationTime: 3000
}
var gameConfig;
// once the window loads...
window.onload = function () {
gameConfig = {
type: Phaser.CANVAS,
parent: 'wheel1',
width: 458,
height: 600,
backgroundColor: 0xffffff,
scene: [playGame]
};
var game = new Phaser.Game(gameConfig);
game.scene.start('PlayGame', { degrees: 50 });
gameConfig = {
type: Phaser.CANVAS,
parent: 'wheel2',
width: 458,
height: 600,
backgroundColor: 0xffffff,
scene: [playGame]
};
var game2 = new Phaser.Game(gameConfig);
game2.scene.start('PlayGame', { degrees:100 });
gameConfig = {
type: Phaser.CANVAS,
parent: 'wheel3',
width: 458,
height: 600,
backgroundColor: 0xffffff,
scene: [playGame]
};
var game3 = new Phaser.Game(gameConfig);
game3.scene.start('PlayGame', { degrees: 150 });
gameConfig = {
type: Phaser.CANVAS,
parent: 'wheel4',
width: 458,
height: 600,
backgroundColor: 0xffffff,
scene: [playGame]
};
var game4 = new Phaser.Game(gameConfig);
game4.scene.start('PlayGame', { degrees: 250 });
gameConfig = {
type: Phaser.CANVAS,
parent: 'wheel5',
width: 458,
height: 600,
backgroundColor: 0xffffff,
scene: [playGame]
};
var game5 = new Phaser.Game(gameConfig);
game5.scene.start('PlayGame', { degrees: 300 });
}
// PlayGame scene
class playGame extends Phaser.Scene {
// constructor
constructor() {
super({ key: "PlayGame" });
}
// method to be executed when the scene preloads
preload() {
//loading assets
this.load.image("wheel", "wheel.png");
this.load.image("pin", "pin.png");
}
// method to be executed once the scene has been created
create(data) {
// adding the wheel in the middle of the canvas
this.wheel = this.add.sprite(gameConfig.width / 2, gameConfig.height / 2, "wheel");
// adding the pin in the middle of the canvas
this.pin = this.add.sprite(gameConfig.width / 2, gameConfig.height / 2, "pin");
// adding the text field
this.prizeText = this.add.text(gameConfig.width / 2, gameConfig.height - 20, "Spin the wheel", {
font: "bold 32px Arial",
align: "center",
color: "black"
});
// center the text
this.prizeText.setOrigin(0.5);
// the game has just started = we can spin the wheel
this.canSpin = true;
//this.input.on("pointerdown", this.spinWheel, this);
this.spinWheel(data.degrees);
}
// function to spin the wheel
spinWheel(degrees) {
// can we spin the wheel?
if (this.canSpin) {
// resetting text field
this.prizeText.setText("");
// the wheel will spin round from 2 to 4 times. This is just coreography
var rounds = Phaser.Math.Between(8, 10);
// var degrees = Phaser.Math.Between(0, 360);
var prize = gameOptions.slices - 1 - Math.floor(degrees / (360 / gameOptions.slices));
// now the wheel cannot spin because it's already spinning
this.canSpin = false;
// animation tweeen for the spin: duration 3s, will rotate by (360 * rounds + degrees) degrees
// the quadratic easing will simulate friction
this.tweens.add({
// adding the wheel to tween targets
targets: [this.wheel],
// angle destination
angle: 360 * rounds + degrees,
// tween duration
duration: gameOptions.rotationTime,
// tween easing
ease: "Cubic.easeOut",
// callback scope
callbackScope: this,
// function to be executed once the tween has been completed
onComplete: function (tween) {
// displaying prize text
this.prizeText.setText(gameOptions.slicePrizes[prize]);
// player can spin again
this.canSpin = true;
}
});
}
}
}
CSS:
#wheel1, #wheel2, #wheel3, #wheel4, #wheel5 {
flex-grow: 1;
margin: 0;
padding: 10px;
}
On the CSS, notice where I remove canvas from it and added padding 10px which you can adjust.
These will result in:

you can center them with flex justify and align, then control their margin. here is how:
.container {
width: 100vw;
height: 150px;
border: 1px solid;
background: lightcoral;
display: flex;
justify-content: center;
align-items: center;
}
.circle {
min-width: 40px;
min-height: 40px;
padding: 40px;
/* this margin will control space between circles */
margin: 0 5px;
background: blue;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
}
<div class="container">
<div class="circle">1</div>
<div class="circle">2</div>
<div class="circle">3</div>
<div class="circle">4</div>
<div class="circle">5</div>
</div>

Related

How to set ScrollToTop Button to be active on viewport height?

At the moment i am using hardcoded height point to trigger visible ScrollToTop Button.
i would love to get solution to be triggered when passing viewport height.
const { scrollDirection } = useScrollDirection()
const { scrollPosition } = useScrollPosition()
const [isVisible, setIsVisible] = useState(false)
const toggleVisible = () => {
if (scrollPosition === 0) {
setIsVisible(false)
}
**if (scrollPosition > 800) {
setIsVisible(true)
} else if (scrollPosition <= 799) {
setIsVisible(false)
}**
}
const scrollToTop = () => {
window.scrollTo({
top: 0,
behavior: "smooth",
})
}
window.addEventListener("scroll", toggleVisible)
you can use window.innerHeight
const toggleVisible = () => {
const viewportHeight = window.innerHeight;
if (scrollPosition === 0) {
setIsVisible(false)
}
**if (scrollPosition > viewportHeight) {
setIsVisible(true)
} else if (scrollPosition <= viewportHeight) {
setIsVisible(false)
}**
}
You can do this by using Intersection Observer (IO)
First you create an element that is just below the viewport initially. And whenever this element comes into view, show the button.
This requires one dummy element which you observe, for the demo I set the html element to position: relative for it to work. Maybe you can use a different element structure, based on your html. Important thing is that you have one element you can observe and trigger the element depending on when it comes into view.
let options = {
rootMargin: '0px',
threshold: 0.1 // when at least 10% of the element is visible we show the button
}
const callback = (entries, observer) => {
const btn = document.querySelector('#scroll-top');
entries.forEach(entry => {
if (entry.intersectionRatio > 0.1) {
// if we are past our 0.1 threshold we show the button
btn.classList.add('visible')
} else {
// otherwise we hide the button
btn.classList.remove('visible')
}
});
};
const observer = new IntersectionObserver(callback, options);
const target = document.querySelector('#button-trigger');
observer.observe(target);
.dummy-viewport {
min-height: 400vh;
}
html {
position: relative;
}
#button-trigger {
position: absolute;
top: 100vh;
left: 10px;
height: calc(100% - 100vh);
/* for demo purposes, don't show the element on the finished site*/
width: 2rem;
outline: 1px solid rebeccapurple;
writing-mode: vertical-rl;
text-orientation: mixed;
}
p {
padding: 0;
margin: 0;
}
#scroll-top {
position: fixed;
bottom: 40px;
right: 10px;
opacity: 0;
transition: .5s opacity;
}
#scroll-top.visible {
opacity: 1
}
<div class="dummy-viewport">
<p> Scroll down ↓ </p>
<button id="scroll-top" type="button"> Scroll to top </button>
</div>
<div id="button-trigger">
<p> When I am visible, I show the button </p>
</div>

How to stop Google Maps from centering on inserted Info Windows

I have a map which I am populating with markers and info windows dynamically. The issue I'm having is that after populating the map, it re-centers automatically on the info windows (but not very well).
It also appears to be centering a few times, and I think it tries to center on the last x added ones (it's not the last, but it's definitely not them all either).
Why this is of particular importance to me is I am populating Info Windows for two cities, and doing so city-by-city, and the map always ends up off-center of the second city (and all its info windows).
I made a fiddle to show the behavior. Adding pins does not re-center, but adding info windows does. (they populate SE of the starting position)
javascript:
var map;
var markers;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {
lat: -30,
lng: 150
},
zoom: 8
});
markers = [];
}
function fire1() {
for (let i = 0; i < 10; i++) {
let position = {
lat: -34.397 + Math.random() - 0.5,
lng: 150.644 + Math.random() - 0.5
}
let point = new window.google.maps.InfoWindow({
position: position,
content: `<span>${i}</span>`
})
point.open(map)
}
}
To prevent opening an InfoWindow from changing the map's center, set the disableAutoPan property to true. From the documentation:
disableAutoPan
Type: boolean optional
Disable auto-pan on open. By default, the info window will pan the map so that it is fully visible when it opens.
let point = new window.google.maps.InfoWindow({
position: position,
content: `<span>${i}</span>`,
disableAutoPan: true
})
proof of concept fiddle
Related questions:
Google Maps API - maps.setCenter doesn't seem to be centering to users position
Center google map on kml, not location
code snippet:
var map;
var markers;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {
lat: -30,
lng: 150
},
zoom: 8
});
markers = [];
}
function fire1() {
for (let i = 0; i < 10; i++) {
var marker = new google.maps.Marker({
position: {
lat: -34.397 + Math.random() - 0.5,
lng: 150.644 + Math.random() - 0.5
},
map: map
});
markers.push(marker);
}
}
function fire2() {
for (let i = 0; i < 10; i++) {
let position = {
lat: -34.397 + Math.random() - 0.5,
lng: 150.644 + Math.random() - 0.5
}
let point = new window.google.maps.InfoWindow({
position: position,
content: `<span>${i}</span>`,
disableAutoPan: true
})
point.open(map)
}
}
#map {
height: 100%;
}
.explanation {
position: absolute;
z-index: 1000;
left: 200px;
top: 20px;
background: white;
padding: 10px;
margin-right: 70px;
border: 2px #666 inset;
}
.fire {
position: absolute;
z-index: 1000;
left: 20px;
background: red;
color: white;
padding: 10px;
}
#fire1 {
top: 60px;
}
#fire2 {
top: 100px;
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
<div id="map"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=API_KEY&callback=initMap" async defer></script>
<button onclick="fire1()" id="fire1" class="fire">
Insert Markers
</button>
<button onclick="fire2()" id="fire2" class="fire">
Insert InfoWindows
</button>
<div class="explanation">When I add markers the map center remains still; but when I add info windows, the map seems to try and center them (badly) - how to I keep the map still?
</div>

Wrong bounding object when translate viewport in FabricJS, user can't select object when click on object

Please help me resolve this problem.
1. I have a text display at postion : left: 10, top: 10.
2. Using viewportTransform to move viewPort to new position : translate by X axis 100 & by Y axis 100
3. The text object is moving to new position
Expected:
User can selected text Object ( 'hello world' ) by click on the text ( at new position )
Actual:
At first time, user can't click on text Object. & object bounder still at old position ( left: 10, top: 10 ). ( see attach image)
Please check in my demo code.
I'm using Fabricjs version 2.4.0 this demo
How to pass through this problem?
Thank you !
var canvasObject = document.getElementById("editorCanvas");
// set canvas equal size with div
$(canvasObject).width($("#canvasContainer").width());
$(canvasObject).height($("#canvasContainer").height());
canvas = new fabric.Canvas('editorCanvas', {
backgroundColor: 'white',
selectionLineWidth: 2,
width: $("#canvasContainer").width(),
height: $("#canvasContainer").height()
});
canvas.controlsAboveOverlay = true;
// Add a text to canvas
var text = new fabric.Text('hello world', { left: 10, top: 10 });
canvas.add(text);
// Transform View
canvas.viewportTransform[4] = 100;
canvas.viewportTransform[5] = 100;
canvas.requestRenderAll();
#canvasContainer {
width: 100%;
height: 100vh;
background-color: gray;
}
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.0/fabric.js"></script>
<div id="canvasContainer">
<canvas id="editorCanvas"></canvas>
</div>
Call object.setCoords(), it will set bounding cordinate after change. And check When-to-call-setCoords
DEMO
var canvasObject = document.getElementById("editorCanvas");
// set canvas equal size with div
$(canvasObject).width($("#canvasContainer").width());
$(canvasObject).height($("#canvasContainer").height());
canvas = new fabric.Canvas('editorCanvas', {
backgroundColor: 'white',
selectionLineWidth: 2,
width: $("#canvasContainer").width(),
height: $("#canvasContainer").height()
});
canvas.controlsAboveOverlay = true;
// Add a text to canvas
var text = new fabric.Text('hello world', {
left: 10,
top: 10
});
canvas.add(text);
// Transform View
canvas.viewportTransform[4] = 100;
canvas.viewportTransform[5] = 100;
setObjectCoords();
canvas.requestRenderAll();
function setObjectCoords(){
canvas.forEachObject(function(object){
object.setCoords();
})
}
#canvasContainer {
width: 100%;
height: 100vh;
background-color: gray;
}
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.0/fabric.js"></script>
<div id="canvasContainer">
<canvas id="editorCanvas"></canvas>
</div>
Not sure if this is still an issue, but you could do the following:
let vpt = [...canvas.viewportTransform];
vpt[4] = 100;
vpt[5] = 100;
canvas.setViewportTransform(vpt);
Had the same issue and that solved it.

section content scaling with background

I am trying to stop my section content from scaling with my section background. the scale of the background is perfect but it seems to make the content scale also, I am using gsap library I have tried creating a container inside the section and give it absolute but nothing I do stops the content inside from scaling
//First the variables our app is going to use need to be declared
//References to DOM elements
var $window = $(window);
var $document = $(document);
//Only links that starts with #
var $navButtons = $("nav a").filter("[href^=#]");
var $navGoPrev = $(".go-prev");
var $navGoNext = $(".go-next");
var $sectionsContainer = $(".sections-container");
var $sections = $(".section");
var $currentSection = $sections.first();
//Animating flag - is our app animating
var isAnimating = false;
//The height of the window
var pageHeight = $window.innerHeight();
//Key codes for up and down arrows on keyboard. We'll be using this to navigate change sections using the keyboard
var keyCodes = {
UP : 38,
DOWN: 40
}
//Going to the first section
goToSection($currentSection);
/*
* Adding event listeners
* */
$window.on("resize", onResize).resize();
$window.on("mousewheel DOMMouseScroll", onMouseWheel);
$document.on("keydown", onKeyDown);
$navButtons.on("click", onNavButtonClick);
$navGoPrev.on("click", goToPrevSection);
$navGoNext.on("click", goToNextSection);
/*
* Internal functions
* */
/*
* When a button is clicked - first get the button href, and then section to the container, if there's such a container
* */
function onNavButtonClick(event)
{
//The clicked button
var $button = $(this);
//The section the button points to
var $section = $($button.attr("href"));
//If the section exists, we go to it
if($section.length)
{
goToSection($section);
event.preventDefault();
}
}
/*
* Getting the pressed key. Only if it's up or down arrow, we go to prev or next section and prevent default behaviour
* This way, if there's text input, the user is still able to fill it
* */
function onKeyDown(event)
{
var PRESSED_KEY = event.keyCode;
if(PRESSED_KEY == keyCodes.UP)
{
goToPrevSection();
event.preventDefault();
}
else if(PRESSED_KEY == keyCodes.DOWN)
{
goToNextSection();
event.preventDefault();
}
}
/*
* When user scrolls with the mouse, we have to change sections
* */
function onMouseWheel(event)
{
//Normalize event wheel delta
var delta = event.originalEvent.wheelDelta / 30 || -event.originalEvent.detail;
//If the user scrolled up, it goes to previous section, otherwise - to next section
if(delta < -1)
{
goToNextSection();
}
else if(delta > 1)
{
goToPrevSection();
}
event.preventDefault();
}
/*
* If there's a previous section, section to it
* */
function goToPrevSection()
{
if($currentSection.prev().length)
{
goToSection($currentSection.prev());
}
}
/*
* If there's a next section, section to it
* */
function goToNextSection()
{
if($currentSection.next().length)
{
goToSection($currentSection.next());
}
}
/*
* Actual transition between sections
* */
function goToSection($section)
{
//If the sections are not changing and there's such a section
if(!isAnimating && $section.length)
{
//setting animating flag to true
isAnimating = true;
//Sliding to current section
TweenLite.set($currentSection, {autoAlpha: 0, display: 'none'});
$currentSection = $section;
TweenLite.set($currentSection, {display: 'block'});
TweenLite.fromTo($currentSection, 0.6, {scale: 0.9, autoAlpha: 0}, {scale: 1, autoAlpha: 1, ease: Power1.easeOut, onComplete: onSectionChangeEnd, onCompleteScope: this});
//Animating menu items
TweenLite.to($navButtons.filter(".active"), 0.5, {className: "-=active"});
TweenLite.to($navButtons.filter("[href=#" + $currentSection.attr("id") + "]"), 0.5, {className: "+=active"});
}
}
/*
* Once the sliding is finished, we need to restore "isAnimating" flag.
* You can also do other things in this function, such as changing page title
* */
function onSectionChangeEnd()
{
isAnimating = false;
}
/*
* When user resize it's browser we need to know the new height, so we can properly align the current section
* */
function onResize(event)
{
//This will give us the new height of the window
var newPageHeight = $window.innerHeight();
/*
* If the new height is different from the old height ( the browser is resized vertically ), the sections are resized
* */
if(pageHeight !== newPageHeight)
{
pageHeight = newPageHeight;
//This can be done via CSS only, but fails into some old browsers, so I prefer to set height via JS
TweenLite.set([$sectionsContainer, $sections], {height: pageHeight + "px"});
//The current section should be always on the top
TweenLite.set($sectionsContainer, {scrollTo: {y: pageHeight * $currentSection.index() }});
}
}
body, div, p {
margin: 0;
padding: 0;
}
body {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-weight: 300;
letter-spacing: 0.0625em;
background-color: #000;
}
h1{
color: #fff;
}
.sections-container {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: hidden;
z-index: 10;
}
.section {
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
display: none;
visibility: hidden;
opacity: 0;
}
#section-1 {
display: block;
visibility: visible;
opacity: 1;
}
.section .centered h1 {
text-align: center;
}
.section .centered p {
text-align: center;
}
#section-1 {
background-color: #5A4748;
}
#section-2 {
background-color: #45959b;
}
#section-3 {
background-color: #778899;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/TweenLite.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/plugins/CSSPlugin.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/plugins/ScrollToPlugin.min.js"></script>
<div class="sections-container">
<div class="section" id="section-1">
<div class="centered">
<h1>1</h1>
</div>
</div>
<div class="section" id="section-2">
<div class="centered">
<h1>2</h1>
</div>
</div>
<div class="section" id="section-3">
<div class="centered">
<h1>3</h1>
</div>
</div>
</div>
Would this be what you're looking for? I basically added a background div
<div id="background"></div>
#background {
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
display: block;
visibility: visible;
opacity: 1;
}
which is assigned a background class based on the section which is currently visible.
var $background = $("#background");
...
$background.classList = "";
TweenLite.set($background, {
className: '+=bg-' + ($sections.index($currentSection) + 1)
});
TweenLite.fromTo($background, 0.6, {
scale: 0.9,
autoAlpha: 0
}, {
scale: 1,
autoAlpha: 1,
ease: Power1.easeOut,
onComplete: onSectionChangeEnd,
onCompleteScope: this
});
You can choose to remove the autoAlpha tween on the section numbers if you so prefer.
//First the variables our app is going to use need to be declared
//References to DOM elements
var $window = $(window);
var $document = $(document);
//Only links that starts with #
var $navButtons = $("nav a").filter("[href^=#]");
var $navGoPrev = $(".go-prev");
var $navGoNext = $(".go-next");
var $sectionsContainer = $(".sections-container");
var $sections = $(".section");
var $background = $("#background");
var $currentSection = $sections.first();
//Animating flag - is our app animating
var isAnimating = false;
//The height of the window
var pageHeight = $window.innerHeight();
//Key codes for up and down arrows on keyboard. We'll be using this to navigate change sections using the keyboard
var keyCodes = {
UP: 38,
DOWN: 40
}
//Going to the first section
goToSection($currentSection);
/*
* Adding event listeners
* */
$window.on("resize", onResize).resize();
$window.on("mousewheel DOMMouseScroll", onMouseWheel);
$document.on("keydown", onKeyDown);
$navButtons.on("click", onNavButtonClick);
$navGoPrev.on("click", goToPrevSection);
$navGoNext.on("click", goToNextSection);
/*
* Internal functions
* */
/*
* When a button is clicked - first get the button href, and then section to the container, if there's such a container
* */
function onNavButtonClick(event) {
//The clicked button
var $button = $(this);
//The section the button points to
var $section = $($button.attr("href"));
//If the section exists, we go to it
if ($section.length) {
goToSection($section);
event.preventDefault();
}
}
/*
* Getting the pressed key. Only if it's up or down arrow, we go to prev or next section and prevent default behaviour
* This way, if there's text input, the user is still able to fill it
* */
function onKeyDown(event) {
var PRESSED_KEY = event.keyCode;
if (PRESSED_KEY == keyCodes.UP) {
goToPrevSection();
event.preventDefault();
} else if (PRESSED_KEY == keyCodes.DOWN) {
goToNextSection();
event.preventDefault();
}
}
/*
* When user scrolls with the mouse, we have to change sections
* */
function onMouseWheel(event) {
//Normalize event wheel delta
var delta = event.originalEvent.wheelDelta / 30 || -event.originalEvent.detail;
//If the user scrolled up, it goes to previous section, otherwise - to next section
if (delta < -1) {
goToNextSection();
} else if (delta > 1) {
goToPrevSection();
}
event.preventDefault();
}
/*
* If there's a previous section, section to it
* */
function goToPrevSection() {
console.log($currentSection.prev().length > 0);
if ($currentSection.prev().length) {
goToSection($currentSection.prev());
}
}
/*
* If there's a next section, section to it
* */
function goToNextSection() {
if ($currentSection.next().length > 0) {
goToSection($currentSection.next());
}
}
/*
* Actual transition between sections
* */
function goToSection($section) {
//If the sections are not changing and there's such a section
if (!isAnimating && $section.length) {
//setting animating flag to true
isAnimating = true;
//Sliding to current section
TweenLite.set($currentSection, {
autoAlpha: 0,
display: 'none'
});
$currentSection = $section;
$background.classList = "";
TweenLite.set($currentSection, {
display: 'block'
});
TweenLite.set($background, {
className: 'bg-' + ($sections.index($currentSection) + 1)
});
//console.log($sections.index($currentSection) + 1);
TweenLite.fromTo($background, 0.6, {
scale: 0.9,
autoAlpha: 0
}, {
scale: 1,
autoAlpha: 1,
ease: Power1.easeOut,
onComplete: onSectionChangeEnd,
onCompleteScope: this
});
TweenLite.fromTo($currentSection, 0.6, {
autoAlpha: 0
}, {
autoAlpha: 1,
ease: Power1.easeOut,
});
//Animating menu items
TweenLite.to($navButtons.filter(".active"), 0.5, {
className: "-=active"
});
TweenLite.to($navButtons.filter("[href=#" + $currentSection.attr("id") + "]"), 0.5, {
className: "+=active"
});
}
}
/*
* Once the sliding is finished, we need to restore "isAnimating" flag.
* You can also do other things in this function, such as changing page title
* */
function onSectionChangeEnd() {
isAnimating = false;
}
/*
* When user resize it's browser we need to know the new height, so we can properly align the current section
* */
function onResize(event) {
//This will give us the new height of the window
var newPageHeight = $window.innerHeight();
/*
* If the new height is different from the old height ( the browser is resized vertically ), the sections are resized
* */
if (pageHeight !== newPageHeight) {
pageHeight = newPageHeight;
//This can be done via CSS only, but fails into some old browsers, so I prefer to set height via JS
TweenLite.set([$sectionsContainer, $sections], {
height: pageHeight + "px"
});
//The current section should be always on the top
TweenLite.set($sectionsContainer, {
scrollTo: {
y: pageHeight * $currentSection.index()
}
});
}
}
body,
div,
p {
margin: 0;
padding: 0;
}
body {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-weight: 300;
letter-spacing: 0.0625em;
background-color: #000;
}
h1 {
color: #fff;
}
.sections-container {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: hidden;
z-index: 10;
}
.section {
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
display: none;
visibility: hidden;
opacity: 0;
}
#section-1 {
display: block;
visibility: visible;
opacity: 1;
}
.section .centered h1 {
text-align: center;
}
.section .centered p {
text-align: center;
}
#background {
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
display: block;
visibility: visible;
opacity: 1;
}
.bg-1 {
background-color: #5A4748;
}
.bg-2 {
background-color: #45959b;
}
.bg-3 {
background-color: #778899;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/TweenLite.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/plugins/CSSPlugin.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/plugins/ScrollToPlugin.min.js"></script>
<div id="background"></div>
<div class="sections-container">
<div class="section" id="section-1">
<div class="centered">
<h1>1</h1>
</div>
</div>
<div class="section" id="section-2">
<div class="centered">
<h1>2</h1>
</div>
</div>
<div class="section" id="section-3">
<div class="centered">
<h1>3</h1>
</div>
</div>
</div>

Vertical and horizontal centering [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Best way to center a <div> on a page vertically and horizontally?
I have a canvas element, and I'd like it to be right in the very center of a page, both vertical and horizontal.
I'm a programmer, and I don't much about CSS. Can anybody help me with centering my canvas both vertically and horizontally?
Here's my current CSS code:
/* Set up canvas style */
#canvas {
font-family: 'pixel';
margin-left: auto;
margin-right: auto;
display: block;
border: 1px solid black;
cursor: none;
outline: none;
}
It's already being centered horizontally, but not vertically, thank you in advance!
this should do the trick:
#canvas {
position: absolute;
top: 50%; left: 50%;
width: 200px;
height: 200px;
margin: -100px 0 0 -100px;
}
The margin top and left has to be negative half the height and width of the element.
The same principal applies if you don't know the width and height and need to calculate it with javascript. Just get the width/height, divide those by half and set the values as a margin in the same way as the example above.
Hope that helps :)
I don't know if this would help, but I wrote this jQuery plugin that might help. I also know this script needs adjustments. It'd adjust the page when needed.
(function($){
$.fn.verticalCenter = function(){
var element = this;
$(element).ready(function(){
changeCss();
$(window).bind("resize", function(){
changeCss();
});
function changeCss(){
var elementHeight = element.height();
var windowHeight = $(window).height();
if(windowHeight > elementHeight)
{
$(element).css({
"position" : 'absolute',
"top" : (windowHeight/2 - elementHeight/2) + "px",
"left" : 0 + "px",
'width' : '100%'
});
}
};
});
};
})(jQuery);
$("#canvas").verticalCenter();
Refined Code + Demo
Please, view this demo in "Full page" mode.
(function($) {
$.fn.verticalCenter = function(watcher) {
var $el = this;
var $watcher = $(watcher);
$el.ready(function() {
_changeCss($el, $watcher);
$watcher.bind("resize", function() {
_changeCss($el, $watcher);
});
});
};
function _changeCss($self, $container) {
var w = $self.width();
var h = $self.height();
var dw = $container.width();
var dh = $container.height();
if (dh > h) {
$self.css({
position: 'absolute',
top: (dh / 2 - h / 2) + 'px',
left: (dw / 2 - w / 2) + 'px',
width: w
});
}
}
})(jQuery);
$("#canvas").verticalCenter(window);
$(function() {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
drawSmile(ctx, 0.9, 'yellow', 'black', 0.75);
});
function drawSmile(ctx, scale, color1, color2, smilePercent) {
var x = 0, y = 0;
var radius = canvas.width / 2 * scale;
var eyeRadius = radius * 0.12;
var eyeXOffset = radius * 0.4;
var eyeYOffset = radius * 0.33;
ctx.save();
ctx.translate(canvas.width / 2, canvas.height / 2);
ctx.beginPath(); // Draw the face
ctx.arc(x, y, radius, 0, 2 * Math.PI, false);
ctx.fillStyle = color1;
ctx.fill();
ctx.lineWidth = radius * 0.05;
ctx.strokeStyle = color2;
ctx.stroke();
ctx.beginPath(); // Draw the eyes
ctx.arc(x - eyeXOffset, y - eyeYOffset, eyeRadius, 0, 2 * Math.PI, false);
ctx.arc(x + eyeXOffset, y - eyeYOffset, eyeRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = color2;
ctx.fill();
ctx.beginPath(); // Draw the mouth
ctx.arc(0, 0, radius * 0.67, Math.PI * (1 - smilePercent), Math.PI * smilePercent, false);
ctx.stroke();
ctx.restore();
}
#canvas {
border: 3px dashed #AAA;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<canvas id="canvas" width="256" height="256"></canvas>

Resources