Stacked divs resizing each other - javascript

This is probably going to be a long one:
I'm trying to make a chat application (similar to Slack) with Electron, React and Socket.io. My issue is mostly dealing with React and CSS/Sass though. Right now I've got a few bootstrap, but I'm not really using the grid system at all, so that can/may be scrapped.
The structure of the page is as follows: I've got a footer with a resizable textarea. above it I've got a div that will be holding messages. That div has overflow-y set to scroll, that way the scrollbar is only for the messages and doesn't take the entire page's space. I want the div to get shorter as the footer grows with the textarea. Right now though the div just extends under the footer (and the scrollbar along with it). Since the messages fill the div there's nothing to scroll and no thumb (I think that's the correct term) in the scrollbar.
React component (I've only included one li for the sake of brevity, but in my code I've got bunch):
import React from 'react';
import { Button, Image, Media, Panel } from 'react-bootstrap';
export default class Page extends React.Component {
constructor(props) {
super(props);
this.state = props;
}
footerResize() {
// code to resize messages div, or at least get some information about
// the footer's height
}
render() {
return (
<div className="page">
<div className="sidebar">
</div>
<div className="container-fluid">
<div classname="messages">
<ul>
<li className="message>
<Media>
<Media.Left>
<Image src="#" />
</Media.Left>
<Media.Body>
<Media.Heading>
Name
</Media.Heading>
Message content
</Media.Body>
</Media>
<li>
</ul>
</div>
<footer>
<textarea defaultValue="test text" />
</footer>
</div>
</div>
);
}
}
_page.scss (most of this is from the file name _page.scss but a few properties are pulled in from other files here so I'm only typing one file's contents):
$dark-grey: #383838;
$default-font-color: #FFFFFF;
$light-grey: #474747;
$light-light-grey: #908E8F
$sidebar-width: 250px;
body {
color: $default-font-color;
overflow: hidden;
}
ul {
list-style: none;
}
.page {
background-color: $light-grey;
height: 100vh;
.sidebar {
background-color: $light-light-grey;
position: fixed;
height: 100%;
width: $sidebar-width;
.container-fluid {
margin-left: $sidebar-width;
padding-left: 0px;
padding-right: 0px;
.messages {
overflow-y: scroll;
}
footer {
background-color: $main-green;
bottom: 0;
padding-bottom: 10px;
padding-left: 10px;
padding-right: 10px;
padding-top: 10px;
position: fixed;
width: calc(100% - #{$sidebar-width});
}
}
}
}
I've tried a bunch of different things to get this to work. I've tried a few node modules. I've tried adding event listeners both by adding ref='footer' to the footer and referring to it as this.refs.footer in when adding the event listener and by giving footer and id and using document.getElementById('footer'). The whatever I try I can't get any information about the footer's size in the footerResize. Any help on this would be appreciated. I don't even know if this is something I should be doing with sass properties or whether I need js/React to do this.

You can try out a flexbox based layout.
This for .container-fluid
display: flex;
flex-direction: column;
This for .messages
flex: 1;
Then you remove position: fixed from footer
What this does: it sets the height of .messages to fill its parent's remaining space. So when footer gets bigger, there is less remaining space and .messages will shrink.
Please note that you will need to add vendor prefixes for flexbox depending on your targeted browser support.

Related

How to position a div inside another div in reactJs?

I want to put the children div on end of parent div , but positioning is not working. i'm using reactJs, NextJs and styled-components for this code;
reactjs code:
<a href={links[indexImg]} target="_blank" >
<Carousel
image={images[indexImg]}
>
<DescriptionText>
<p>{descriptions[indexImg]}</p>
</DescriptionText>
</Carousel>
</a>
styled-componentes code:
export const DescriptionText = styled.div`
color: white;
background-color: black;
background-position: 20px;
opacity: 0.5;
`;
export const Carousel = styled.div`
position: relative;
border-radius: 50px;
border: solid;
border-width: 3px;
border-color: #C2C2C2;
margin: 0;
height: 100%;
width: 100%;
justify-content: flex-end;
background-size: cover;
background-position: center;
background-image:url(${props => props.image});
`;
If your .inner division has a position of absolute and your .outer one gets position relative, the .inner division will adjust itself inside the .outer one. For example: if you want the .inner one to stick to the bottom of the .outer one you can do this:
.outer {
position: relative
}
.inner {
postion: absolute;
bottom: 0
}
first of all install bootstrap from terminal using the command
npm install react-bootstrap bootstrap
suppose you are working with components like Leftsidebar.js , Rightsidebar.js and Content.js which you have imported to index.js
to do this you have install bootstrap in your react.js
follow the steps
index.js blow
import React from 'react';
import ReactDom from 'react-dom';
import Leftsidebar from './Leftsidebar';
import Rightsidebar from './Rightsidebar';
import Content from './Content';
ReactDom.render(
// outer most div
<div class='row'>
<div class='col-4'>
<Leftsidebar/>
</div>
<div class='col-4'>
<Content/>
</div>
<div class='col-4'>
<Rightsidebar/>
</div>
</div>
,documment.getelementbyId('root');
);
simple we have used the grid system to divide the screen into 4 different part out of 12 secondly the above code is just typed in the text editor .but my aim was to guide you how to show data in different layout or positions using react js and it work because i myself use row column to arrange data in position and it is the easiest method .

Smart DOM Insertion (preserve styles of child element)

This is a very odd question, of which I am fairly confident I already know the answer, however, before I go ahead with the fix that I am trying to avoid, I thought it was worth asking others as you may see this from a different angle
I am currently writing a plugin that takes a certain element (can be any DOM node), and wraps it with a div. The purpose of the plugin is to add a 'blinds' effect to elements which can then be used to reveal the element on scroll.
Note: Wrapping with a div is absolutely essential to the functionality I am implementing.
My question, quite simply, is anybody aware of a smart way to preserve the styles from the element being wrapped and ensure it visually remains the same as it was before the div wrapping, and, whilst retaining the dimensions so another div can be inserted within the wrapper and be the same dimensions of it's sibling.
See this very basic example (before and after - notice the blue blind):
.test {
display: flex;
flex-flow: column;
height: 200px;
text-align: center;
}
.test:nth-child(1) {
background: #999;
}
.test:nth-child(2) {
background: #666;
}
.test > * {
flex: 0 1 auto;
}
.test h1 {
margin: auto 0 0;
color: #fff;
}
.test p {
margin: 0 0 auto;
color: #fff;
}
.test-wrapper {
position: relative;
width: max-content; /* Fix for example purposes */
margin: 0 auto; /* Fix for example purposes */
}
.test-wrapper .blind {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: blue;
opacity: 0.5;
}
<div class="test">
<h1>Before wrapper inserted</h1>
<p>Some description</p>
</div>
<div class="test">
<div class="test-wrapper">
<div class="blind"></div>
<h1>After wrapper inserted</h1>
</div>
<p>Some description</p>
</div>
Before answering, these are the solutions I am trying to avoid:
'copying' or 'moving' the styles (or certain styles) from the child to the parent as this is likely to cause a huge mess... Open to suggestions though
Defining styles for test-wrapper in the site's CSS as test-wrapper is a plugin specific element.
The obvious, and very easy, solution is to just define the styles for the wrapper instead of the child in my CSS (SCSS). I appreciate this may be the only way, but I ideally want to avoid this as what I am building is a plugin and I want the HTML/CSS to work with and without the element wrapper in place.

Quill: How to prevent toolbar from scrolling and set the height?

I am trying to follow the sample at https://quilljs.com/playground/#autogrow-height but have problems setting the height of the editor box and preventing the toolbar from scrolling off-screen.
My code is:
<div id="editorcontainer" style="height:10em; min-height:100%; overflow-y:auto;">
<div id="editor" name="editor" style="min-height:100%; height:auto;"></div>
</div>
<script>
var quill = new Quill("#editor",{
modules: {
toolbar: [ ... ]
},
scrollingContainer: "#editorcontainer",
theme: "snow"
});
</script>
The JS Filddle is available at https://jsfiddle.net/OldGeezer/xpvt214o/556844/
The output looks like this:
There are two problems:
The tool bar is not fixed and scrolls.
The vertical scrollbar has a scrollable region all the time, even when the editor is empty.
How do I solve these two problems?
I had to modify two of quill's classes to get what I wanted. Like so
.ql-container.ql-snow {
height: auto;
}
.ql-editor {
height: 150px;
overflow-y: scroll;
}
My solution was to add an additional encapsulating div with position:relative to establish the reference frame for ql-toolbar which is set to position:absolute.
The editorcontainer is then given a margin-top:3em to hold the toolbar (when it is short enough to fill a single row).
<div style="position:relative;margin-top:5em;">
<div id="editorcontainer" style="height:10em; min-height:100%;
overflow-y:auto;margin-top:3em">
<div id="editor" style="min-height:100%; height:auto;"></div>
</div>
</div>
<style>
.ql-toolbar { position: absolute; top: 0;left:0;right:0}
</style>
The working fiddle is at https://jsfiddle.net/OldGeezer/oLq2bnzv/
You will need to modify one of quill's class
.ql-container.ql-snow {
border: none;
height: 150px;
overflow: scroll;
}
For those who suffered from Angular quill in this question,
I suggest you should add this code in the style.css.
.ql-toolbar {
position: sticky;
}
.ql-container {
overflow-x:auto;
height: 300px; /* whatever you what */
}
The tool bar is not fixed and scrolls.
You can change the CSS of the toolbar like the following:
.ql-toolbar {
position: fixed;
top: 0;
}
The vertical scrollbar has a scrollable region all the time, even when the editor is empty.
You can lower the min-height of the editor so it's lower than the container (80% for example).

How to scroll beyond fixed position elements on a page with TOC without using JS?

Any ideas how to fix this problem: On a page with TOC (table of contents) with links pointing to hashtags within the same page, when the browser scrolls down other fixed position elements hide it. The browser should scroll further down to avoid being hidden by the fixed elements.
Fiddle to demonstrate this problem: https://jsfiddle.net/fcro6mth/ Click Section One or Section Two - the browser scrolls down to it but its hidden by the fixed header
Solution with JS: https://jsfiddle.net/fcro6mth/1/
Can you think of any solution that doesn’t involve JS?
Code from JS fiddle:
HTML:
<header>
This is the fixed position header
<nav>
Section One
Section Two
Section Three
</nav>
</header>
<div class="body">
This is the body.
<section id="section1">This is section one</section>
<section id="section2">This is section two</section>
<section id="section3">This is section three</section>
</div>
CSS:
section {
background: lightgrey;
margin: 20px 0;
padding: 20px 10px;
height: 300px;
}
header {
background-color: grey;
position: fixed;
top: 0;
padding: 10px;
width: 100%;
box-sizing: border-box;
left: 0;
color: white;
}
.body {
margin: 70px 10px 0 10px;
}
JavaScript:
$("nav a").click(function (event) {
var $target = $(event.currentTarget),
$scrollToTarget = $($target.attr("href")),
$header = $("header"),
prop = {
scrollTop: $scrollToTarget.offset().top - $header.outerHeight(true)
},
speed = 1000;
$('html, body').animate(prop, speed);
});
Check this: https://stackoverflow.com/a/13555927/2112228
Nice example to make hidden anchors for offsetting your sections.
Updated version of your fiddle:
https://jsfiddle.net/fcro6mth/4/
Solution
I wrapped your sections in div-wrappers gave them the IDs, padded them down and pulled them back up with a negative margin.
This results in the exact same appearance, but the links do what you want them to do.
Example:
HTML:
<div id="section1" class="wrapper">
<section >This is section one</section>
</div>
CSS:
.wrapper {
padding-top: 50px;
margin-top: -50px;
}
I have struggled with this issue a lot in designing a webpage with a combined banner / navbar of about 300px fixed at the top of a page full of short items linked to by anchor links from the website's home page.
The problem I have found with the "margin-top: -XXpx; padding-top: XXpx" approach is that the invisible padding overlaid the preceding item, meaning that active content (ie. links) were blocked. I overcame this by applying positioning to the anchored elements and setting the z-index so that the first item was on top of the stack with each subsequent item lower in the stack - like this:
CSS
.anchored-element {
padding-top: 300px;
margin-top: -300px;
position: relative;
}
HTML
<div class="anchored-element" style="z-index: 99">FIRST ITEM</div>
<div class="anchored-element" style="z-index: 98">SECOND ITEM</div>
<div class="anchored-element" style="z-index: 97">THIRD ITEM</div>
... etc
This provided a fix that worked for me across Firefox, Safari and Chrome on my desktop, and on my iOS devices. I hope this helps others tackle this very frustrating issue in bootstrap!

Position badge over corner of image automatically

I have a layout where images "float" within a certain area. The layout looks like this:
The source like this:
<div class="free_tile">
<a class="img_container canonical" href="/photos/10">
<img class="canonical" src="http://s3.amazonaws.com/t4e-development/photos/1/10/andrew_burleson_10_tile.jpg?1303238025" alt="Andrew_burleson_10_tile">
<!-- EDIT: I am aware that I can put the badge here. See the edit notes and image below. -->
</a>
<div class="location">Houston</div>
<div class="taxonomy"> T6 | Conduit | Infrastructure </div>
</div>
The CSS looks like this (in SCSS):
div.free_tile { width: 176px; height: 206px; float: left; margin: 0 20px 20px 0; position: relative;
&.last { margin: 0 0 20px 0; }
a.img_container { display: block; width: 176px; height: 158px; text-align: center; line-height: 156px; margin-bottom: 10px; }
img { margin: 0; border: 1px solid $dark3; display: inline-block; vertical-align: middle; #include boxShadow;
&.canonical { border: 1px solid $transect; }
}
.location, .taxonomy { width: 176px; }
.location { font-weight: 700; }
.taxonomy { line-height: 10px; font-size: 10px; text-transform: uppercase; height: 20px; overflow: hidden; }
}
div.transect_badge { height: 20px; width: 20px; background: url('/images/transect-badge.png'); }
So, basically the images are sitting vertically-aligned middle and text-aligned center, and they have a maximum width of 176 and max height of 158, but they're cropped to maintain the original aspect ratio so the actual top corner of each image falls differently depending on which image it is.
I have a badge that I'd like to put in the top corner of certain images (when the image is "canonical"). You see the style for this above (div.transect_badge).
The problem, of course, is I don't know where the top corner of the image will be so I can't hardcode the position via CSS.
I assume that I'll need to do this via jQuery or something. So, I started with a jQuery method to automatically append the badge div to any canonical images. That works fine, but I can't figure out how to position it over the top left corner.
How can this be done? (ideally using just HTML and CSS, but realistically using JS/jQuery)
--EDIT--
Here's the problem: The image is floating inside a container, so the corner of the image might fall anywhere inside the outer limits of the container. Here's an example of what happens if I try to use position:absolute; top:0; left:0 inside the same container the image is bound by:
It took some tryouts, but here it is: the size independent image badge positioner.
HTML:
<div class="tile">
<span class="photo">
<img src="/photos/10.jpg" alt="10" /><ins></ins>
</span>
<p class="location">Houston</p>
<p class="taxonomy">T6 | Conduit | Infrastructure</p>
</div>
CSS:
.tile {
float: left;
width: 176px;
height: 206px;
margin: 0 20px 20px 0;
}
.photo {
display: block;
width: 176px;
height: 158px;
text-align: center;
line-height: 158px;
margin-bottom: 10px;
}
a {
display: inline-block;
position: relative;
line-height: 0;
}
img {
border: none;
vertical-align: middle;
}
ins {
background: url('/images/badge.png') no-repeat 0 0;
position: absolute;
left: 0;
top: 0;
width: 20px;
height: 20px;
}
Example:
In previous less successful attempts (see edit history), the problem was getting the image vertically centered ánd to get its parent the same size (in order to position the badge in the top-left of that parent). As inline element that parent doesn't care about the height of its contents and thus remains to small, but as block element it stretches to hís parent's size and thus got to high, see demonstration fiddle. The trick seems to be to give that parent a very small line-height (e.g. 0) and display it as an inline-block. That way the parent will grow according to its childs.
Tested in Opera 11, Chrome 11, IE8, IE9, FF4 and Safari 5 with all DTD's. IE7 fails, but a center-top alignment of the photo with badge at the right position isn't that bad at all. Works also for IE7 now because I deleted the spaces in the markup within the a tag. Haha, how weird!
EDIT3: This solution is very similar to my original solution. I didn't really look at your code much so I should have noticed this earlier. Your a tag is already wrapping each image so you can just add the badge in there and position it absolute. The a tag doesn't need width/height. Also you must add the badge image at the beginning of your a tag.
Demo: http://jsfiddle.net/wdm954/czxj2/1/
div.free_tile {
width: 176px;
height: 206px;
float: left;
}
a.img_container {
display: block;
margin-bottom: 10px;
}
span.transect_badge {
display:block;
position: absolute;
height: 20px;
width: 20px;
background-image: url('/images/transect-badge.png');
}
HTML...
<a class="img_container canonical" href="/photos/10">
<span class="transect_badge"></span>
<img class="canonical" src="path/to/img" />
</a>
Other solutions...
In my code I'm using SPAN tags so simulate images, but it's the same idea. The badge image, when positioned absolute, will create the desired effect.
Demo: http://jsfiddle.net/wdm954/62faE/
EDIT: In the case that you need jQuery to position. This should work (where .box is your container and .corner is the badge image)...
$('.box').each(function() {
$(this).find('.corner')
.css('margin-top', ( $(this).width() - $(this).find('.img').width() ) / 2);
$(this).find('.corner')
.css('margin-left', ( $(this).height() - $(this).find('.img').height() ) / 2);
});
EDIT2: Another solution would be to wrap each image with a new container. You would have to move the code that you use to center each image to the class of the new wrapping container.
Demo: http://jsfiddle.net/wdm954/62faE/1/
$('.img').wrap('<span class="imgwrap" />');
$('.imgwrap').prepend('<span class="badge" />');
Technically you can just add something like this to your HTML though without using jQuery to insert it.
Use an element other than <div>, e.g. <span> and put it inside your <a> element after the <img> element. Then, give the <a> element position:relative; and the <span> gets position:absolute; top:0px; left:0px;. That is, if you don't mind the badge also being part of the same link - but it's the easiest way. Also, the reason for using <span> is to keep your HTML4 valid, <div> would still be HTML5 valid, however.
I did find one solution using jQuery. I don't prefer this because it noticably impacts page loading, but it is acceptable if nothing else will work. I'm more interested in NGLN's idea which seems promising but I haven't entirely figured out yet. However, since this thread has picked up a lot of traffic I thought I'd post one solution that I came up with for future readers to consider:
Given this markup:
<div class="free_tile">
<a class="img_container canonical" href="/photos/10">
<img class="canonical" src="http://s3.amazonaws.com/t4e-development/photos/1/10/andrew_burleson_10_tile.jpg?1303238025" alt="Andrew_burleson_10_tile">
<span class="transect-badge"></span>
</a>
<div class="location">Houston</div>
<div class="taxonomy"> T6 | Conduit | Infrastructure </div>
</div>
Same CSS as in question except:
span.transect-badge { display: block; height: 20px; width: 20px; position: absolute; background: url('/images/transect-badge.png'); }
Then this jQuery solves the problem:
$(function() {
$('img.canonical').load( function() {
var position = $(this).position();
$(this).next().css({ 'top': position.top+1, 'left': position.left+1 });
});
});
Like I said, though, this incurs noticeable run-time on the client end, so I'd prefer to use a non JS solution if I can. I'll continue to leave this question open while I test out and give feedback on the other solutions offered, with hopes of finding one of them workable without JS.

Categories

Resources