I've been trying for several hours to both vertically and horizontally center a div with no specific width or height in a parent div that has a max-width and max-height but will be responsive. I've looked at both CSS and JS/jQuery options with nothing working properly.
As you can see, it's a thumbnail preview for a video. When in a normal state, it just shows the thumbnail with a play icon above it. In a hover state, it changes the play button to an orange one, displays the title, and has a black transparent overlay above the thumbnail.
Now, this would be easy to do with CSS if the site wasn't responsive. But, as the browser width decreases, the thumbnail sizes decrease.
Here's the HTML I'm using:
<article class="movie"><a href="#">
<div class="movie-overlay">
<div class="movie-play"></div>
<h2 class="movie-title">Title Goes Here</h2>
</div> <!-- end .movie-overlay -->
<div class="movie-thumb"><img src="thumbs/thumb.jpg"/></div>
</a></article> <!-- end #post- -->
And here's my CSS:
.movie-archive .movie {
width: 50%;
height: auto;
max-width: 480px;
position: relative;
overflow: hidden;
float: left;
}
.movie-archive .movie .movie-overlay {
width: 100%;
height: 100%;
position: absolute;
text-align: center;
}
.movie-archive .movie:hover .movie-overlay {background: rgba(0, 0, 0, 0.6);}
.movie-archive .movie .movie-play {
background: url("images/play-icon#2x.png") no-repeat center 0;
background-size: 94px 190px;
width: 100%;
height: 95px;
}
.movie-archive .movie:hover .movie-play {background-position-y: -95px;}
.movie-archive .movie .movie-title {
font-size: 17px;
letter-spacing: -0.01em;
font-weight: 700;
color: #ffffff;
display: none;
padding: 10px 50px 0;
}
.movie-archive #latest-top.movie:hover .movie-title, .movie:hover .movie-title {display: block;}
.movie-archive .movie .movie-thumb img {
width: 100%;
height: 100%;
display: block;
}
I've tried various things from adding another div and using the display: table trick to adding padding as a percentage, and using JS. Nothing seems to work. Does anyone have any suggestions? I would really appreciate it. Thanks!
Not that it really matters, but I am using WordPress for this site.
The container and the elemented you want centered should have properties like this:
.movie-archive .movie {
width: 50%;
height: auto;
max-width: 480px;
position: relative;
overflow: hidden;
float: left;
}
.movie-archive .movie .movie-overlay {
width: 100%;
height: 100%;
left: 50%;
margin-left: -50%; //half of width
top: 50%;
margin-top: -50%; //half of height
position: absolute;
text-align: center; //only if you want the text to be centered
}
Source: http://designshack.net/articles/css/how-to-center-anything-with-css/
try this:
$(document).ready(function() {w = $(window).width();
h = $(window).height();
jQuery.each($('.centerony'), function(i, val) {
lung = $(val).css('height');
a = (h * 0.5) - ((parseInt(lung)) * 0.5);
$(val).css('position', 'absolute');
$(val).css('top', a + 'px')
});
jQuery.each($('.centeronx'), function(i, val) {
larg = $(val).css('width');
a = (w * 0.5) - ((parseInt(larg)) * 0.5);
$(val).css('position', 'absolute');
$(val).css('left', a + 'px')
});
$(window).resize(function() {
k = $(window).width();
z = $(window).height();
jQuery.each($('.centeronx'), function(i, val) {
larg = $(val).css('width');
a = (k * 0.5) - ((parseInt(larg)) * 0.5);
$(val).css('left', a + 'px')
})
jQuery.each($('.centerony'), function(i, val) {
lung = $(val).css('height');
a = (z * 0.5) - ((parseInt(lung)) * 0.5);
$(val).css('position', 'absolute');
$(val).css('top', a + 'px')
});
});
});
Add to the element you want to center class 'centerony' and class 'centeronx', and set parent's div (the one which has max-width and max-height with position:relative. It should work.
<div id="outdiv" class="outside" style="position:relative">
<div class="in_div centerony centeronx">I am centered!</div>
</div>
You have to use include jQuery to use it. :)
PAY ATTENTION -------
the code i wrote works according to window's size, and not parent's div size.
If you want to adapt to your case, change the values of vars w,h,k,z, making their value in relation with parent's div size instead of window size. for example w = $('#outdiv').width() instead of w = $(window).width();
Related
TL;DR: How to keep the div children proportional to the div itself?
I have a div, containing various elements like text, images, icons etc. It keeps 16:9 aspect ratio and fills as much viewport it can, while resizing the browser window, the div (with background different from the body background) changes size well, though the contents are staying the same size which is bad because I'm trying to make a presentation website which needs to look the same at various resolutions. How do I make the child elements align and resize properly inside the div?
I tried using viewport units though it didn't turn out really well.
My Code:
I tried using % units to set font size and then use em to scale other things but it didn't work. I also tried using only % units to set all properties but it did not work either
body {
background: black;
user-select: none;
margin: 0;
height: 100vh;
}
.container2 {
overflow: auto;
box-sizing: border-box;
resize: both;
overflow: auto;
max-width: 100%;
height: 100%;
display: flex;
justify-content: center;
}
.presentation-place {
user-select: none;
background: white;
top: 50%;
transform: translate(0, -50%);
position: absolute;
align-items: center;
aspect-ratio: 16 / 9;
}
#media screen and (max-aspect-ratio: 16 / 9) {
.presentation-place {
width: 100vw;
}
}
#media screen and (min-aspect-ratio: 16 / 9) {
.presentation-place {
height: 100vh;
}
}
.slide {
font-size: 100%;
position: absolute;
top: 0;
bottom: 0;
margin: 0 auto;
width: 100%;
height: 100%;
overflow: hidden;
background: red;
background-position: center center;
}
.title1 {
margin-left: 1em;
font-size: 6em;
position: absolute;
margin-top: 2em;
}
<html>
<body>
<div class="container">
<div class="presentation-place">
<div class="slide s1">
<h1 class="title1">test</h1>
</div>
</div>
</div>
</body>
</html>
Make sure to avoid specific units like cm, px etc because those are fixed units no matter the scale of the site itself or the monitor, the use of Units like % since vh/vw didnt work. % scales relative to the size of the monitor or website, so this should help. Alternativly you could use aspect-ratio because it scales relative to the size of the parent element
The project:
I made a 3 items slider just using CSS and JS. I'm trying to adjust the proportion of one item to make sliding based on this proportion.
The problem:
the proportion isn't fixed and there is a slight space from the left side of all items and between items themselves. It seems they have borders that take a tiny space. and that space also affects sliding itself. I don't know if it's a CSS or JS problem!
Source Code on Codepen
HTML
<div id="slider">
<div class="SlideContainer">
<div class="img">
<img src="https://www.nicepng.com/png/detail/11-112605_punk-cat-berkley-cats-illustrations.png">
</div>
<h1 style="text-align:center;">1</h1>
</div>
<div class="SlideContainer">
<div class="img">
<img src="https://i.pinimg.com/736x/84/78/b9/8478b93283dc6eac074d437097a9fe74.jpg">
</div>
<h1 style="text-align:center;">2</h1>
</div>
...... etc
</div>
CSS
#slider {
height: 500px;
margin: 0;
padding: 0 .5%;
overflow: hidden;
white-space: nowrap;
scroll-behavior: smooth;
}
.SlideContainer{
vertical-align: top;
background-color: purple;
color: white;
height: 99% ;
margin: .5% 0;
width: 33%;
display: inline-block;
}
.img {
overflow: hidden;
max-width:200px;
max-height:200px;
border-radius: 50%;
display: block;
margin: 10px auto 0 auto;
text-align: center;
}
.img img{
height: 200px;
width: 200px;
}
JS
var Container = document.getElementById("slider");
var unitWidth = (Container.offsetWidth/3);
var slidesNo = (document.getElementsByClassName("SlideContainer").length - 2);
var i = 0;
var positionInfo = Container.getBoundingClientRect();
var height = positionInfo.height;
var width = (positionInfo.width/3);
function SlideLoop(){
var interval = setInterval(function(){
Container.scrollTo((unitWidth * i), 0);
//Container.scrollBy(unitWidth, 0);
i++;
if(i == slidesNo) {
i = 0;
clearInterval(interval);SlideLoop();
}
}, 1500);
};
SlideLoop();
Your problem is with using white-space: nowrap; in the slider and display: inline-block; in the slider items.
Using such methods to display items is not recommended because it would cause strange unexpected behavior. I suggest you learn flexbox. This is a great and easy guide that will help you.
as for your problem, change those css elements like this and it should work propely:
#slider {
height: 500px;
margin: 0;
padding: 0 .5%;
overflow: hidden;
scroll-behavior: smooth;
display: flex; /* displays items horizontally */
}
.SlideContainer{
vertical-align: top;
background-color: purple;
color: white;
height: 99% ;
margin: .5% 0;
min-width:33%; /* force the minimum width of items */
}
I found a piece of code that almost does what I want except I want it to be horizontal / based on mouse Y instead of X. Now I understand that in the js X will be changed to Y, but I struggle with rotating the divs.
Also, if I want to put some text over it, how would I do so that the background change affects the text colour (so if the text is black and half of the background is black, to make sure once when the black background overlays the text, text colour changes to another or gets inverted for example?
Also also, I tried to figure out in js which part dictates the responsiveness of the mouse movement, i.e., how would you do so that the colour shifting is not lagging after the mouse but I couldn't figure out?
https://codepen.io/erutuf/pen/NJLwqV
haml
#banner-wrapper.banner-wrapper
.banner.design
.banner-content
.banner.dev
.banner-content
scss
body {
margin: 0;
padding: 0;
.banner-wrapper {
position: relative;
width: 100%;
height: 400px;
overflow: hidden; background:red;
}
.banner {
position: absolute;
overflow: hidden;
&.dev {
margin-left: -500px;
width: calc(50vw + 500px);
.banner-content {
margin-left: 500px; background:black;
}
}
.banner-content {
height: 400px;
}
img {
width: 100vw;
}
}
}
js
document.addEventListener('DOMContentLoaded', function(){
let banner = document.getElementById('banner-wrapper');
let devLayer = banner.querySelector('.dev');
let delta = 0;
banner.addEventListener('mousemove', function(e){
delta = (e.clientX - window.innerWidth / 2) * 0.5;
devLayer.style.width = e.clientX + 500 + delta + 'px';
});
})
you can play with JS + CSS. The following code can be your starting point :).
btw i'm adapting code from your link https://codepen.io/erutuf/pen/NJLwqV
document.addEventListener("DOMContentLoaded", function(){
let banner = document.getElementById("banner-wrapper");
let devLayer = banner.querySelector(".dev");
let delta = 0;
// play with div's height
banner.addEventListener("mousemove", function(e){
delta = (e.clientY - window.innerHeight / 2) * 0.5;
devLayer.style.height = e.clientY + delta + "px";
});
})
<div class="banner-wrapper" id="banner-wrapper">
<div class="banner design">
<div class="banner-content">BANNER TEXT</div>
</div>
<div class="banner dev">
<div class="banner-content"></div>
</div>
</div>
<style type="text/css">
body {
margin: 0;
padding: 0;
}
body .banner-wrapper {
position: relative;
width: 100%;
height: 200px;
overflow: hidden;
background: red;
}
body .banner {
position: absolute;
overflow: hidden;
}
body .banner.dev {
width: 100%;
/* play with responsiveness here. note that 0.1 is more responsive than 0.5. more info : https://www.w3schools.com/css/css3_transitions.asp */
-webkit-transition: height 0.2s linear;
transition: height 0.2s ease;
}
body .banner.dev .banner-content {
background: black;
}
body .banner .banner-content {
height: 400px;
}
body .banner img {
width: 100%;
}
.banner.design {
margin-top: -25px;
height: 50px;
top: 50%;
font-size: 50px;
/* set color & mix-blend-mode for text color vs background color effect. more info : https://css-tricks.com/methods-contrasting-text-backgrounds/ */
mix-blend-mode: difference;
color: #fff;
z-index: 1;
margin-left: -175px;
left: 50%;
width: 350px;
}
</style>
I need to set text over image. The size of the image\div containing the image is fixed. I got some input above the image that the user insert some text.
the text is injected via props to the "image component" and then i need to display it over the image. the trick is that the text have fixed place to be. at the bottom of the image. the text should not overflow the image borders of course and need to span at the maximum. I mean that if the text is "short" (low amount of characters) the font size should increase and vice versa using java script function.
the problem with my function its not "flexible" enough, the ratio between the font size and the text length is too "hard coded" with fixed values that changed the desired result.
<template>
<div class="img-container z-depth-4">
<img class="img-to-edit" :src="this.urlChanges">
<p class="text-append">{{textToAppend}}</p>
</div>
</template>
<script>
export default{
props: ['urlChanges', 'textToAppend'],
data () {
return {
limit: 25,
font: 35,
offset: 0
}
},
mounted() {
let self = this
$( document ).ready(function() {
//that's an input from the parent component
$('#textarea1').on('keypress', function(e) {
let that = $(this);
let textLength = that.val().length;
if(textLength+self.offset > self.limit) {
$('.text-append').css('font-size', self.font + 'px');
self.font -= 5;
self.offset -=5;
}
});
});
},
}
</script>
and the style
<style scoped>
.img-container {
width: 800px;
height: 430px;
overflow: hidden;
background: #ccc;
margin: 10px;
line-height: 150px;
position: relative;
text-align: center;
color: white;
}
.img-to-edit {
max-width: 100%;
max-height: 100%;
vertical-align: middle;
flex-shrink: 0;
min-width: 100%;
min-height: 100%;
}
.text-append{
position: absolute;
top: 80%;
left: 50%;
transform: translate(-50%, -50%);
overflow: hidden;
}
</style>
im not sure about my css definition.
You can use the vh or vw for font size the ratio will remain the same for almost very resolution
font-size: 5vh
or
font-size: 10vw
http://jsfiddle.net/3qMnM/1/
HTML:
<div class="info-panel"></div>
<div class="image">
<img src="http://placehold.it/960x1400">
</div>
CSS:
.image {
height: 100%;
width: auto;
margin-right: 200px;
}
.info-panel {
position: fixed;
width: 200px;
height: 100%;
background-color: red;
right: 0px;
}
I'm trying to scale images down (never up) dynamically to fit into the image-div (without cropping), which is variable in height (100%) and width (set to auto). The image also needs to be centered (vertically and horizontally) and have equal padding of a few pixels top and bottom.
There is an info panel next to the image container as you can see in the fiddle, but I'm not sure if this is relevant.
Do my statements make sense?
Thanks, I have spent way too much time experimenting with this already! :/
If I understand correctly, you want something like this.
It scales down if the image is too large, but keeps the original size when it fits inside the window. In other words, it never scales up - only down.
It is a combination of CSS and some jQuery:
This short JS centers the image vertically:
function verticallyCenterImage(){
var $img = $('.image img'),
windowHeight = $(window).outerHeight();
if($img.height() < windowHeight){
var delta = windowHeight - $img.height();
$img.css('margin-top', (delta / 2) + 'px');
}else{
$img.attr('style', '');
}
}
And this line of CSS keeps the image centered horizontally:
.image {
padding-right: 200px;
text-align: center; /* <- this one */
max-height: 100%;
overflow: hidden;
}
And to keep the original size of the image, I just set the max height and width on the img inside the .image class, like so:
.image img {
max-width: 96%;
max-height: 96%;
margin: 2%;
}
You can adjust the size and margins to your needs, just remember to keep them in relation too each other :)
Some of the techniques discussed here could work for you:
http://css-tricks.com/centering-in-the-unknown/
The trick there is to use table elements, or CSS 2.1 table display.
Edit: More approaches here: http://www.vanseodesign.com/css/vertical-centering/
You are mixing px with %. If you want to achieve that only by CSS, you need to use % for both widths:
.image {
width: 85%;
}
.image img {
width: 100%;
}
.info-panel {
position: fixed;
width: 15%;
height: 100%;
background-color: red;
right: 0px;
}
... otherwise, you have to use JS to calculate the current available width on the left side and assing it the .image div:
HTML
<div class="info-panel"></div>
<div class="image">
<img src="http://placehold.it/960x1400" />
</div>
CSS
.image {
min-height: 600px;
width: auto;
}
.image img {
width: 100%;
}
.info-panel {
position: fixed;
width: 200px;
height: 100%;
background-color: red;
right: 0px;
}
JS (jQuery)
$(document).ready(function() {
$('.image')
.css('min-height', 'auto')
.height($(window).height())
.width($(window).width() - $('.info-panel').width())
;
});