<th> cells not keeping width - javascript

Note: These issues only occur in Firefox or Chrome. IE does not appear to have the same problem.
HTML
<div id="renewals-div">
<label for="renewals">Renewals:</label>
<input type="hidden" name="renewal_count" id="renewal_count" value="0">
<table id="renewals">
<thead>
<tr data-num="-1" class="header">
<th class="date_column">Date</th>
<th class="details_column">Details</th>
</tr>
</thead>
<tbody>
<!-- rows populated by ajax call on load -->
</tbody>
</table>
<br>
<label for="add_renewal-div"></label> <!-- spacer -->
<span id="renewal_buttons-span">
<button type="button" id="add_renewal">Add</button>
<button type="button" id="remove_renewal">Remove</button>
</span>
</div>
CSS
form {
width: 100%;
padding-left: 2em;
}
form fieldset {
border: none;
margin: 0 0;
padding: 0 0;
}
form div {
box-sizing: border-box;
width: 100%;
margin-bottom: .2em;
}
form label {
display: inline-block;
padding-bottom: 10px;
width: 30%;
max-width: 15em;
vertical-align: top;
}
form input[type=submit] {
/*float: left;*/
width: 75px;
height: 35px;
}
.radio_group {
width: 70%;
}
form input[type=text] {
width: 50%;
max-width: 400px;
display: inline-block;
}
/* Renewals table and other stuff */
table {
table-layout:fixed;
width: 51%;
max-width: 404px;
border-collapse: collapse;
display: inline-block;
}
table td, table th {
text-align: center;
vertical-align: middle;
border: 1px solid black;
}
table input {
box-sizing: border-box;
-webkit-box-sizing:border-box;
-moz-box-sizing: border-box;
width: 95% !important;
margin: 3px 3px;
}
table tr:hover:not(.selected):not(.header) {
background-color: #D6ADFF;
}
table .selected {
background-color: #522D80;
color: white;
}
.header {
width: 100%;
}
.date_column {
width: 25%;
}
.details_column {
width: 75%;
}
#renewal_buttons-span button {
width: 5em;
height: 2.5em;
}
/*********************************/
div.ui-datepicker {
font-size:10px;
}
/*#media (max-width: 650px) {*/
JS
$('#remove_renewal').click(function() {
var next = $('.selected').next('tr');
$('.selected').remove();
if (next.length === 0) {
$('#renewals tbody tr').last().click();
} else {
next.click();
}
});
My issue is with the "Renewals:" table. I am allowing the user to add and delete rows to the table. By default two test rows are loaded on page load. If you remove both of them, suddenly the table columns no longer respect their width properties. Since the <th> columns are the only ones left, I assume they are the ones not honoring my width setting. How can I get them to honor width even when no rows exist?
EDIT: The side issue below is resolved. I misunderstood CSS selectors as overwriting each other based on the last one in the CSS file. Apparently the styles are decided by the selector that is the most specific. By changing my second selector to input[type=text] it was specific enough to override the previous one without the use of !important.
Side issue:
I have a second problem with the width of the input boxes in the table. I have two CSS selectors affecting input width:
form input[type=text] {
width: 50%;
max-width: 400px;
display: inline-block;
}
table input {
box-sizing: border-box;
-webkit-box-sizing:border-box;
-moz-box-sizing: border-box;
width: 95% !important;
margin: 3px 3px;
}
As you can see, the selector setting the width to 95% comes after the previous one so it should take precedence. However, if I take out the !important the 50% width overrides the 95%! In CSS, I thought that for conflicting styles, the last one declared/selected wins? So why do I still need !important since the style I want to be applied is last?

I set a width on the #date_col and was able to prevent the collapse
I notice that .header doesn't have any styles associated with it, so you could try putting a width value in it and then letting the two cells fill its parent container. One is at 25% and the other at 75%, but they don't have a parent to reference.
The !important declaration is a symptom of a specificity war with ID selectors and can turn into a mess. I'd encourage you to use classes instead of ID's to prevent this problem.
I think this article explains it well. Towards the bottom

If you want to know why you need important, remove it.
Then, in Chrome, go to development tools.
Inspect the element that has the problem. In the right hand panel, in "Styles", you will see that property crossed.
Now, go to Computed Style, the panel above.
Go to the property; in this case width. deploy it pressing the arrow, and you will see what is the guilty rule

My answer was deleted by a moderator, and converted to a 'comment'
i first noticed your table is displayed has an inline-block.
Try display:table. All the mechanics of TABLE layout will obey.
table {
border-collapse: collapse;
display: table; /* you can even remove this part*/
max-width: 404px;
table-layout: fixed;
width: 51%;
}
To make it keep layout with it's label, just float the previous label left.
Carry on

Related

how to set select box width based on child table width - css

In my vue application, i have designed one select box which is having table component. While clicking the select box, table is visible in container. Now, problem is that i am not able to set dynamic width of select box based on table width.
Now, table rows are overlapping because of fixed width of select box. It is opening the container upside. There is a scroll because of width.
Here is my code
<div class="dropdown_grid my-dropdown--medium>
... div related to title and toggle
// here is the container
<div
class="dropdown_grid_container"
ref="floating"
v-ur-attach-root:fit
v-click-outside.anchor="close"
>
<ul><li><my-table :items="items" :headers="headers"
single-select></my-table></li></ul>
</div>
</div>
Css for this
.dropdown_grid {
display: inline-block;
position: relative;
min-width: 150px;
width: 100%;
color: #333333;
cursor: pointer;
}
.dropdown_grid_container {
width: 100%;
position: absolute;
margin-top: -1px;
min-width: 500px;
overflow-y: auto;
background-color: #FFFFFF;
border: 1px solid #959595;
z-index: 200;
max-height: 200px;
padding: 8px 1px;
margin-left: 2px;
}
.my-dropdown--medium {
font-size: 14px;
line-height: 24px;
height: 32px
I have seen multiple post regarding this but not able to set it dynamic width. How to make it dynamic based on child width?
As you have the class or ID for your element, you are able to access the width with document.getElemnt functions . So you can define a function for when you are opening your table or showing it, then access the width of your table by document functions and assign it to whatever element you want.

How to make two columns same height dynamically

I hava a page with two columns. I would like to textarea height mimic left column height. Left column is short when webpage loads, but when user starts expanding various properties (checkboxes + dropdownmenus) it grows based on hidden divs. But my textarea is still small in right column and making it staticly bigger does not look good.
I want it to grow per left column height. Not sure how to achieve that.
EDIT:
Once height: 100%; was added to textarea it solved the issue with columns growth.
But I ran into another two issues.
Textarea in right column overlaps that column on page load. When I try to resize, it suddenly jumps to the column properly. Weird behavior.
here is the pic - textarea overlaps column
Left column context is not aligned properly with right. How I am going to align or justify context of both columns so they end up like this:
here is the pic - final look
My CSS:
body {
height: 100%;
position: relative;
background: #000000;
color: #66adff;
font-size: 105%;
font-family: serif, Arial, Helvetica
}
.column {
border: 5px solid #333;
}
.container{
display: flex;
}
.columnleft {
width: 45%;
padding: 10px;
display: table-cell;
}
.columnright {
width: 45%;
padding: 10px;
display: table-cell;
}
textarea.out {width: 100%; height: 100%; box-sizing: border-box;}
EDIT 2:
Issue 1 - I had text inside the column which pushed area down
Issue 2 - all was fixed with proper padding
Thanks all for replies.
I think you could do this without js, but use CSS Grid instead.
Example:
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr; // the width of each column
grid-template-rows: auto; // row height will auto-adjust to contents
}
<div class="grid-container">
<div class="column-left">
...some dynamic content
gets bigger and bigger and bigger and bigger and bigger
</div>
<div class="column-right">
might be empty or small or large
</div>
</div>
The grid row height will always adjust to the height of the largest content which will make both columns the same height.
Since you're using flex, the right column should be automatically adjusting to match the left column. It sounds like your issue is that the textarea is not expanding automatically to match its container (right column.)
If that's the case, try this simple fix - in your CSS, set textarea height to 100% to automatically fill its parent:
textarea {
height: 100%;
};
Here's an example answer:
Textarea to fill a parent container exactly, with padding
The reason your code wasn't working was because you didn't set the height to your textarea settting the height to 100% will always make it fit the maximum size of it's container (<div>) also i have added box-sizing: border-box; so that you can add padding to your columnright.
A better explanation about box-sizing can be found here (just won't explain here because i couldn't do better then this): https://css-tricks.com/box-sizing/
function f_anyEvent(){
var leftcolumnHeight = document.getElementById('columnleft').style.height.value;
if (document.getElementById('columnleft').style.height != document.getElementById('columnright').style.height)
document.getElementById('columnright').style.height = leftcolumnHeight.value;
}
document.getElementById('add').addEventListener('click', function() {
let columnleft = document.getElementById('columnleft');
columnleft.innerHTML += '<h1>a</h1>';
});
.row{
display: flex;
}
.column {
border: 1px solid #333;
}
.columnleft {
float: left;
width: 45%;
padding: 10px;
display: table-cell;
}
.columnright {
float: left;
width: 45%;
padding: 10px;
display: table-cell;
}
textarea {
width: 100%;
height: 100%;
box-sizing: border-box;
}
<div class="row">
<div id="columnleft" class="column columnleft">
</div>
<div id="columnright" class="column columnright">
<textarea></textarea>
</div>
</div>
<button id="add">
add
</button>
Every time you click add it will add an <h1> to your left column and your textarea will get the same height as columnleft.
Here's a basic demo of an interface similar to yours that uses display: grid on the parent container to automagically keep the two inner divs the same height. (Click on the blue details element to trigger a height change.)
It's wonderfully simple. (Thanks for inspiring me to finally learn how grid works.)
// The JavaScript isn't needed for the dynamic styling. (It just copies the text.)
const
left = document.getElementById("left"),
right = document.getElementById("right");
left.addEventListener("change", showOutput);
function showOutput(event){
right.innerHTML = this.querySelector("#reasons").value
}
div { max-width: 400px; border: 1px solid grey; }
details{ margin: 10px 5px; color: #0000DD; text-decoration: underline; }
/* This is where the magic happens */
#container { display: grid; grid-template-columns: 1fr 1fr; }
#left{ padding: 10px; }
#right { white-space: pre-wrap; }
<div id="container">
<div id="left">
<label> <input type="checkbox"/> I like pie </label>
<details>
<summary>Type your reasons here</summary> <textarea id="reasons"></textarea>
</details>
</div>
<div id="right"></div>
</div>

Hide the "resizing" handle in a resizable div?

There are a few other questions which are similar, but none works or seems in the right area. I'm trying to make a table's columns' widths resizable. My table is a normal HTML table, except that it has the Bootstrap 4 class table (maybe they could have thought of a different name...!).
My css looks like this:
.resizable-div {
resize: horizontal;
overflow: auto;
margin: 0px;
padding: 0px;
border: 1px solid black;
display:block;
min-width: 100px;
min-height: 30px;
}
The relevant bit of JS where I add the cell to the table row with a resizable div inside it, and text inside that, is like this:
row.appendChild(cell);
const resizableTdDiv = document.createElement( 'div' );
resizableTdDiv.classList.add( 'resizable-div');
cell.appendChild( resizableTdDiv );
const cellTextNode = document.createTextNode(isHeader ? fieldName : value);
resizableTdDiv.appendChild(cellTextNode);
The result works fine: resizable columns. Hurrah. There is only one fly in the ointment:
I can get rid of the borders, of course. I just want to lose those pesky handler triangles in the bottom right corners... all of them!
I realise users have to be given an idea that they are able to resize the columns... but I'd be perfectly happy to do that some other way if I could replace those triangle icons with 100% transparent ones (for example).
Edit
Here's a JSFiddle! Amazingly easy to do!
You can do this in WebKit based browsers currently with the ::-webkit-resizer pseudo element.
div{
overflow:auto;
resize:both;
width:50%;
}
div:nth-of-type(2)::-webkit-resizer{
background:transparent;
}
<div>
Not Hidden
</div>
<div>
Hidden
</div>
WebKit provides a pseudo-element for this ::-webkit-resizer and you can hide those triangles by applying display: none, -webkit-appearance: none, or background: transparent.
For Firefox or anything without WebKit an alternative / workaround would be to position a custom handle over top of each resizable div. This may require some different markup though.
.wrapper {
position: relative;
display: inline-block;
}
.resizable-div {
position: relative;
resize: both;
overflow: auto;
margin: 0px;
padding: 0px;
border: 1px solid black;
display:block;
min-width: 100px;
min-height: 30px;
}
.handle {
position: absolute;
bottom: 0;
right: 0;
width: 20px;
height: 20px;
background: black;
pointer-events: none;
}
/* ::-webkit-resizer {
background: transparent;
} */
<div class="wrapper">
<div class="resizable-div"></div>
<div class="handle"></div>
</div>

Z-Index of Material Dropdown component not layering underneath a fixed div when opened

Objective:
I would like the Header, Tab Section, and the Radio Button Section to be fixed in a form (see image below). Meaning that they should always be in view, and never have any overlapping elements.
The form looks like the following:
This is working fine when I simply scroll down on the form:
The Problem:
When I open the Angular Material dropdown, it overlaps over the Radio Button Section:
Here is the HTML. The highlighted sections are the elements that I want to be fixated on the form:
And here is the CSS for the 3 sections
//Header:
.module__header {
position: fixed;
top: 0px;
z-index: 1001;
display: flex;
height: 35px;
width: 100%;
background-color: #082749;
color: #FFFFFF;
font-size: 14px;
font-weight: 500;
align-items: center;
justify-content: stretch;
padding: 0;
margin-bottom: 0;
}
// Tab Section:
.mat-tab-label-container {
position: fixed;
top: 35px;
padding-top: 10px;
z-index: 1001;
width: 100%;
background: #fff;
}
// Radio Button Section:
.timaticFullTextView {
padding-top: 35px;
padding-left: 15px;
padding-bottom: 15px;
background: #fff;
z-index: 1001;
position: fixed;
width: 100%;
border-bottom: 1.5px solid gray;
}
I have tried changing the cdk-overlay-container to a z-index of <1001, but that still is overlapping the Radio Button Section.
How can I have the opened dropdown display underneath all 3 sections?
Edit: Adding screenshot to show the cdk-overlay that is giving issues. I have tried removing and lowering the z-index, but it doesn't have any effect
The problem is that mat-tab-body has z-index: 1 and this won't allow your fixed view inside to have a higher elevation. You can remove the z-index from mat-tab-body put then your content without a z-index won't be clickable anymore so you have to add a z-index and position to your not fixed content.
The code would have to look something like this:
<mat-tab>
<mat-tab-body> <!-- <-- added automatically -->
<div class="tab-header"></div>
<div class="tab-content"></div>
</mat-tab-body>
</mat-tab>
::ng-deep mat-tab-body {
z-index: unset !important;
}
.tab-header {
position: fixed;
z-index: 1001;
}
.tab-content {
position: relative;
z-index: 1;
}
You've found the right element whilst applying styles to the wrong one.
Here is how I made it work
.cdk-global-overlay-wrapper, .cdk-overlay-container {
z-index: 99999 !important;
}

Is there a way to have a table cell stay fixed at a given height AND enable word-wrap?

I want to place room labels at different locations on a map. The rooms are of variable heights and so the "height" attribute is set in the JavaScript/React code for each room label.
My problem is that if I want the height of the cell not to expand with the length of longer strings, I have to turn off word-wrap. However, I would like to wrap words and have many lines of the name, so long as it does not exceed the height I set.
Is there a way to do this? Here's my current set up, which just stretches to display the whole string.
React:
return <div className={cx('roomLabelContainer')}
style={{left: startX, top: startY, width: width, height: height}}>
<table className={cx('roomLabel')}>
{this.props.roomLabelName}
</table>
</div>;
CSS:
.roomLabelContainer {
display: table;
margin: auto;
overflow: hidden;
position: absolute;
table-layout: fixed;
}
.roomLabel {
display: table-cell;
line-height: 100%;
margin: auto;
overflow: hidden;
text-align: center;
vertical-align: middle;
width: 100%;
word-wrap: break-word;
}
Since table rows wont respect a max-height property (per W3C spec) a possible solution is to wrap your cell contents in a div and use that to constrain the row.
<td class="roomLabel"><div class="constrain">text...</div></td>
And the CSS
.constrain {
position: relative;
max-height: /* choose */;
overflow: hidden;
}

Categories