bootstrap 3 responsive table with fixed first column - css

I am targeting mobile specifically so I have a Bootstrap responsive table. Its just a div with the bootstrap class "table-responsive" and a table nested inside with the classes "table table-striped table-bordered table-hover table-condensed".
Is there any easy way to make sure that the first column is fixed (not scrolling horizontally)? On mobile devices, its likely that there will be scrolling every time but the first column contains what are essentially table headers.

If you're only targeting mobile devices then this may work for you: you can clone the first column in your table and apply position:absolute so it appears "in front" when you scroll the rest of the table.
For this you'd need some basic jquery code and a custom CSS class:
jQuery
$(function(){
var $table = $('.table');
//Make a clone of our table
var $fixedColumn = $table.clone().insertBefore($table).addClass('fixed-column');
//Remove everything except for first column
$fixedColumn.find('th:not(:first-child),td:not(:first-child)').remove();
//Match the height of the rows to that of the original table's
$fixedColumn.find('tr').each(function (i, elem) {
$(this).height($table.find('tr:eq(' + i + ')').height());
});
});
CSS
.table-responsive>.fixed-column {
position: absolute;
display: inline-block;
width: auto;
border-right: 1px solid #ddd;
background-color: #fff; /* bootstrap v3 fix for fixed column background color*/
}
#media(min-width:768px) {
.table-responsive>.fixed-column {
display: none;
}
}
Here's a working demo for this approach

Related

Timepicker inside table

In my Angular app, I'm using the timepicker widget from ngx-bootstrap.
It looks fine when used outside a table:
However, for some reasons it looks super-ugly when used inside a table element:
I'm not using any custom css code.
It took me a while to figure out what was happening there. The problem was some bootstrap style attached to .table and similar classes (e.g. rules applied to .table td) was breaking the timepicker's layout (since it internally also uses a table element).
My solution was applying this style:
timepicker {
table {
tr {
background-color: transparent !important;
th,
td {
padding: 0 !important;
vertical-align: middle !important;
border: none !important;
}
}
}
}

How can I change CSS pseudo-element property dynamically?

I understood:
You can't modify pseudo elements through JavaScript since they are not part of the DOM
I also knew we could add properties in pseudo-element by appending style -- more.
However, the appending solution could only add value. adding doesn't mean the ability of changing dynamically. I also need to the ability of replacing the property value.
Therefore, I tried to use attr() to change background image dynamically. However, currently attr only supports content property - more.
So what else I can try here?
In order to adding more context of the question, basically, I want to dynamically update avatar image in chat. The avatar image is setted in pseudo-element(before and after). Here is the code-pen of Chat UI -- http://codepen.io/clintioo/pen/HAkjq
Thank you very much!
As said in other answers, there is a way to inject styles that will afect your pseudo element.
A somewhat simpler workaround for your specific case could be to just inherit the background from the base element (since you are not using it)
function changebkg () {
target1 = document.getElementById('test');
target1.style.backgroundImage = "url(http://placekitten.com/1000/750)";
}
#test {
font-size: 40px;
position: relative;
display: inline-block;
color: black;
background-size: 0px;
background-color: lightblue;
}
#test:after {
content: "";
position: absolute;
left: 200px;
top: 20px;
width: 200px;
height: 200px;
background-image: inherit;
border: solid 1px;
background-size: contain;
}
<div id="test" onclick="changebkg();">click me</div>
Here is the part in the "duplicate" that shows how to get, add and change CSS pseudo-element property dynamically using Javascript.
Stack snippet
/* on page load */
window.addEventListener('load', function() {
/* get button and add click event to it */
var btn = document.querySelector('button');
btn.addEventListener("click", function(){
/* get first <p> element */
var el1 = document.querySelector('p.first');
/* get second <p> element */
var el2 = document.querySelector('p.second');
/* get first <p> pseudo's "content" property value */
var str = window.getComputedStyle(el1,':before').getPropertyValue('content');
/* get first <p> pseudo's "color" property value */
var col = window.getComputedStyle(el1,':before').getPropertyValue('color');
/* dynamically add a rule to the stylesheet so the second <p>
will get the same "content"/"color" value as the first */
document.styleSheets[0].addRule('p.second:before', 'content: ' + str + ' ; color: ' + col + ';');
/* dynamically add a rule to the stylesheet that override the
first <p> "color" to green */
document.styleSheets[0].addRule('p.first:before', 'color: green;');
});
});
p.first:before {
content:"foo";
color: red;
}
button {
display: block;
width: 220px;
margin-top: 50px;
}
<p class="first">This is a paragraph</p>
<p class="second">This is another paragraph</p>
<button>Change/Add pseudo properties</button>
As you have just learned, attr() isn't supported anywhere else but the content property at the moment. If your requirement is to set other CSS properties dynamically, then I'm afraid you can't do much of that within CSS alone. The closest you can get is to generate static CSS dynamically through a script, as shown in a number of answers to the first question you link to.
In the specific case of user avatars, I don't see why you aren't just marking those up using img elements instead, which would obviate this issue entirely.
You can create a css file and then inject it into the DOM.
var avatar_css_for_avatar = document.createElement('style');
avatar_css_for_avatar.type = 'text/css';
avatar_css_for_avatar.innerHTML = '.user-avatar-id:before { background-image: url(url_of_image); }';
document.getElementsByTagName('head')[0].appendChild(avatar_css_for_avatar);
document.getElementById('someElementId').className = 'user-avatar-id';

p:dataTable CSS row change onclick

I have one question concerning <p:dataTable> row CSS.
I have implemented a dataTable. In the css-File i have specified row-height as:
.ui-datatable tbody td {
height: 30px;
}
If you click on one row, the data and columns changes. Now I want to change the height of the rows (after the click on the row) too. Is there a possibility to change the row-height of the datatTable in the backing bean method public void onRowSelect(SelectEvent event){...} or in some other way?
If you can use css this works for me:
tr[role=row].ui-state-highlight td{
height: 10px;
...
}

SASS: Can I get element count in one class?

I want to position divs next to each other spaced equally and reposition them if the window size is changed. For that I think I need SASS. One time there may be 14 divs, other 10 divs in one class and I want them to be spaced equally depending on the count and the screen size. Can I get element count in SASS for one class?
Or you can do that with pure css and flex property
.equalSpaces {
overflow: hidden;
display: flex;
}
.equalSpaces p {
padding: 5px;
margin: 0;
background-color: #000;
border: 1px solid #999;
}
.equalSpaces div {
display: inline-block;
flex: 1; /* to make all blocks equal */
}
An example: http://jsfiddle.net/LbxyLmpg/
edit: #cimmannon suggestion display: inline-block;
You just need to use jQuery for this. Not AJAX or SASS. The reason is, AJAX is server side and SASS is just precompiled CSS, nothing more. So, you need to make it this way:
$(document).ready(function(){
$(".equalSpaces").each(function(){
totalDivs = $(this).find("div").length;
$(this).find("div").width(100/totalDivs + "%");
});
});
Fiddle: http://jsfiddle.net/praveenscience/h72horvz/

Programmatically scroll ng-repeat with overflow:hidden

I'm using the following markup (JADE) to build a pagination with AngularJS and Foundation.
ul.pagination
li.arrow: a «
li(ng-repeat="month in months | orderBy:'_id'" ng-class="month._id === shownMonth ? 'current' : ''")
a(ng-href="#/months/{{month._id}}") {{ month._id | monthid:'short' }}
li.arrow#right-arrow: a »
In the CSS, I've set overflow: hidden. This gets me this:
Perfect so far, but obviously this could get long.
How can I make this scroll when the user clicks on the little arrow symbols at the end?
I've tried doing stuff like $(...).animate({left: '-=20'}) but it simply gets ignored (I'm guessing because of the Foundation css). Any ideas?
UPDATE
I've got a semi-working solution, but it's ugly.
I have attached an ng-show condition to the repeated list items as such:
li(ng-repeat="month in months | orderBy:'_id'" ng-class="month._id === shownMonth ? 'current' : ''" ng-show="month._id >= min && month._id <= max")
and after loading my data I do
$timeout(function() {
var availableWidth = $('ul.pagination').width() - 2 * $('ul li.arrow').width();
var itemWidth = $('li:not(.arrow)').width();
var total = Math.floor(availableWidth / itemWidth);
$scope.min = $scope.shownMonth - Math.floor(total / 2);
$scope.max = $scope.shownMonth + Math.floor(total / 2);
});
Then I basically just need to adjust min and max in an ng-click handler for the arrow buttons. This works, more or less, but for some reason, availableWidth gets calculated to much, much smaller than the space that's actually available for it - it's off by about 600px! Why?
Animating the left position makes no sense. What you want to animate is the horizontal scroll position (element.scrollLeft).
Also, consider removing your arrows out of the list of months. They don't make sense semantically in that list, and they'll end up constraining you when you want to scroll just the months but leave the arrows in place.
Edited to add fiddle: http://jsfiddle.net/R9QcB/5/ I did this with jQuery for quickness, but scrollLeft is a native javascript property.
It's the CSS that's actually important here moreso than the javascript:
#pagination {
text-align: center;
}
.nav {
display: inline-block;
vertical-align: middle;
}
ul {
display: inline-block;
vertical-align: middle;
max-width: 75%;
overflow: hidden;
white-space: nowrap;
}
li {
display: inline-block;
list-style: none;
color: #fff;
background: #aaa;
padding: 0.25em 0.5em;
margin: 0 0.5em;
}
Basically, you need a containing element that you can update the scrollLeft position of. That containing element has an overflow: hidden on it so that its child elements sit in a series inside the container (which is a result of white-space: nowrap).

Resources