diff --git a/INSTALL.txt b/INSTALL.txt
index 44c1fcd..b5eaa30 100644
--- a/INSTALL.txt
+++ b/INSTALL.txt
@@ -1,12 +1,15 @@
 INSTALL INSTRUCTIONS FOR CSS MODULE
-----
-
-- Copy the css module folder into the sites/all/modules directory or sites/example.com/modules directory. 
-- Login as site administrator
-- Activate the css module as usual (Administer > Site building > Modules)
-- Activate the css editing for the node types you need (Administer > Content management > Content types)
-- Enable the "create css for nodes" permissions *only* for the administrator groups (trusted users, see below)
-
-IMPORTANT: note that the CSS editing permissions should be given only to trusted users (administrators). Malicious users which have this permission might break your site design and also introduce security issues (XSS).
-
-
+-----------------------------------
+
+- Copy the css module folder into the sites/all/modules directory or
+  sites/example.com/modules directory. 
+- Login as site administrator.
+- Activate the css module as usual (Administer > Modules).
+- Add CSS fields to the node types you need (Administer > Content management
+  > Content types) or other entity types.
+- Enable the "create css for nodes" permissions *only* for the administrator
+  groups (trusted users, see below).
+
+IMPORTANT: note that the CSS editing permissions should be given only to
+trusted users (administrators). Malicious users which have this permission
+might break your site design and also introduce security issues (XSS).
diff --git a/README.txt b/README.txt
index 5c952ef..b7a8c34 100644
--- a/README.txt
+++ b/README.txt
@@ -1,18 +1,24 @@
-
 CSS MODULE
------
-
-The CSS module adds, for users with enough permissions and enabled nodes, a CSS field on the node creation page.
+----------
 
-Users might insert CSS rules in the CSS node field and those rules will be parsed on the node viewing.
-This way CSS experienced users might create complex CSS based designs for nodes contents.
+The CSS module adds, for users with enough permissions, a CSS field on the
+entity (node, user, etc.) creation and edit pages.
 
-IMPORTANT: note that the CSS editing permissions should be given only to trusted users (administrators). Malicious users which have this permission might broke your site design and also introduce security issues (XSS).
+Users might insert CSS rules in the CSS node field and those rules will be
+parsed on the node viewing.  This way CSS experienced users might create
+complex CSS based designs for entity contents.
 
+IMPORTANT: note that the CSS editing permissions should be given only to
+trusted users (administrators). Malicious users which have this permission
+might break your site design and also introduce security issues (XSS).
 
 For installation instructions see INSTALL.txt
 
+Please send comments to the official project issue queue:
+http://drupal.org/project/issues/css
 
-Please send comments to:
-Fabio Varesano: fvaresano at yahoo dot it
-
+Original author: Fabio Varesano <fvaresano at yahoo dot it>.
+Updated for Drupal 5 by Christopher Skauss <christopher skauss at gmail>.
+Modified Drupal 5 Version by Whispero.
+Updated for Drupal 6 by Joshua Chan <josh at joshuachan dot ca>.
+Updated for Drupal 7 by Scott Reynen, DamienMcKenna.
diff --git a/css.info b/css.info
index b4dac2c..db3c3e4 100644
--- a/css.info
+++ b/css.info
@@ -1,4 +1,4 @@
 name = CSS
-description = Permits adding CSS rules to node contents.
+description = Permits adding CSS styling to specific entities.
 package = Content
-core = "6.x"
\ No newline at end of file
+core = "7.x"
diff --git a/css.install b/css.install
deleted file mode 100644
index 29b23f5..0000000
--- a/css.install
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-/**
- * @file
- * CSS module install file.
- */
-
-/**
- * Database table schema definition.
- */
-function css_schema() {
-  $schema['css'] = array(
-      'description' => t('CSS rules added to individual nodes.'),
-      'fields' => array(
-        'nid' => array(
-          'description' => t('The {node}.nid for the CSS.'),
-          'type' => 'int',
-          'unsigned' => TRUE,
-          'not null' => TRUE,
-          'default' => 0
-        ),
-        'css' => array(
-          'description' => t('The primary identifier for the relation.'),
-          'type' => 'text',
-          'not null' => FALSE,
-        ),
-      ),
-      'primary key' => array('nid'),
-  );
-  return $schema;
-}
-
-
-/**
- * Implementation of hook_install().
- */
-function css_install() {
-  drupal_install_schema('css');
-}
-
-
-/**
- * Implementation of hook_uninstall().
- */
-function css_uninstall() {
-  drupal_uninstall_schema('css');
-}
diff --git a/css.module b/css.module
index 02d82d7..046c84e 100644
--- a/css.module
+++ b/css.module
@@ -1,232 +1,201 @@
-<?php
-
-/**
- * @file
- * Adds the support for css on node creation.
- * We add the ability for each node to have an attached css
- *
- * @author Fabio Varesano <fvaresano at yahoo dot it>
- * @updated to Drupal 5 by Christopher Skauss <christopher skauss at gmail dot com>
- * @modified drupal 5 Version by Whispero
- * @updated for Drupal 6 by Joshua Chan <josh at joshuachan dot ca>
- *
- * To store this extra information, we need an auxiliary database table.
- *
- * Database definition:
- * @code
-   CREATE TABLE css (
-      nid int(10) unsigned NOT NULL default '0',
-      css text NULL default NULL,
-      PRIMARY KEY (nid)
-    )
- * @endcode
- */
-
-/**
- * Implementation of hook_help().
- */
-function css_help($path, $arg) {
-  switch ($path) {
-    case 'admin/modules#description':
-      // This description is shown in the listing at admin/modules.
-      return t('A module which add customizable CSS support.');
-  }
-}
-
-/**
- * Implementation of hook_menu()
- */
-function css_menu() {
-  $items = array();
-  // defines the callback for getting the css file. we use
-  // css/get as path instead of only css to avoid that in some
-  // installs users have yet a directory called css
-  $items['css/get'] = array(
-    'title' => 'css',
-    'path' => 'css/get', 
-    'page callback' => 'css_get',
-    'access arguments' => array('access content'),
-    'type' => MENU_CALLBACK,
-  );
-  return $items;
-}
-
-/**
- * Implementation of hook_perm()
- */
-function css_perm() {
-  return array('create css for nodes');
-} 
-
-/**
- * Implemenation of hook_form_alter()
- */ 
-function css_form_alter(&$form, $form_state, $form_id) {
-  //Add a text area to the form where users will put their csses rules.
-  if (user_access('create css for nodes') && variable_get('css__' . $form['#node']->type, FALSE)) {
-    if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
-      $node = $form['#node'];
-      // create a fieldset so we can collapse it
-      $form['css_fieldset'] = array(
-        '#type' => 'fieldset',
-        '#title' => t('CSS Rules'),
-        '#collapsible' => TRUE,
-        '#collapsed' => empty($node->css_css), // show uncollapsed if we have some css rule set
-      );
-      $form['css_fieldset']['css_css'] = array(
-          '#type' => 'textarea',
-          '#title' => t('CSS Rules'),
-          '#default_value' => $node->css_css,
-          '#cols' => 60,
-          '#rows' => 10,
-          '#description' => t('Insert here the css rules for this node. You can use css defined for other nodes using <em>@import "?q=css/get/x";</em> where x is the identification number of the node which contains the css you want to use.'),
-          '#attributes' => NULL,
-          '#required' => FALSE,
-      );
-    }
-  }
-  // Create a settings on content types configuration page
-  // which enable to activate/deactivate css editing for a node type	
-  if (isset($form['#node_type']) && 'node_type_form' == $form_id) {
-    $form['workflow']['css_' . $node->type] = array(
-          '#type' => 'checkbox',
-          '#title' => t('Enable CSS Editing.'),
-          '#return_value' => 1,
-          '#default_value' => variable_get('css__' . $form['#node_type']->type, FALSE),
-          '#description' => t('Users with the <em>create css for nodes</em> permission will be able to edit CSS rules to be applied to this node type.'),
-    );
-  }
-} 
-
-/**
- * Implementation of hook_nodeapi().
- */
-function css_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
-  static $prev_op = NULL;
-
-  if (variable_get('css__'. $node->type, FALSE)) { // check that CSS editing is enabled for the given node type
-    switch ($op) {
-
-      // Controls for valid input data
-      case 'validate':
-        // Check for potentially malicious tags
-        $pattern = '~<\s*\/?\s*(style|script|meta)\s*.*?>~i';
-        if (preg_match($pattern, $node->css_css)) {
-          form_set_error('css_css', t('Please do not include any tags.'));
-        }
-        break;
-
-      // Now that the form has been properly completed, it is time to commit the new
-      // data to the database.
-      case 'insert':
-        if (!empty($node->css_css) && user_access('create css for nodes')) {
-          db_query("INSERT INTO {css} (nid, css) VALUES (%d, '%s')", $node->nid, $node->css_css);
-        }
-        break;
-
-      // If the form was called to edit an existing node rather than create a new
-      // one, this operation gets called instead. We use a DELETE then INSERT rather
-      // than an UPDATE just in case the rating didn't exist for some reason.
-      case 'update':
-        if (user_access('create css for nodes')) {
-          db_query("DELETE FROM {css} WHERE nid = %d", $node->nid);
-          if (!empty($node->css_css)) {
-            db_query("INSERT INTO {css} (nid, css) VALUES (%d, '%s')", $node->nid, $node->css_css);
-          }
-        }
-        break;
-
-      // If the node is being deleted, we need this opportunity to clean up after
-      // ourselves.
-      case 'delete':
-        db_query('DELETE FROM {css} WHERE nid = %d', $node->nid);
-        break;
-
-      // Now we need to take care of loading one of the extended nodes from the
-      // database. An array containing our extra field needs to be returned.
-      case 'load':
-        $object = db_fetch_object(db_query('SELECT css FROM {css} WHERE nid = %d', $node->nid));
-        return array('css_css' => $object->css);
-        break;
-
-      // Using nodeapi('view') is more appropriate than using a filter here, because
-      // filters transform user-supplied content, whereas we are extending it with
-      // additional information.
-      case 'view':
-        if ($prev_op == 'validate') {
-          // 'validate' immediately followed by 'view' means this is a preview
-          if ($node->css_css) {
-            $css = '<style type="text/css" media="all"> '.
-                   css_sanitize($node->css_css, 'preview') .
-                   ' </style>';
-            drupal_set_html_head($css, 'preview');
-          }
+<?php
+/**
+ * @file
+ * Adds the ability for each entity to have an attached css.
+ */
+
+/**
+ * Implements hook_menu().
+ */
+function css_menu() {
+  $items = array();
+
+  // Defines the callback for getting the css file. We use css/get as path
+  // instead of only css to avoid conflicts in some installs where users have
+  // an existing directory called css.
+  $items['css/get/%/%/%/%'] = array(
+    'title' => 'css',
+    'path' => 'css/get/%/%/%/%',
+    'page arguments' => array(2, 3, 4, 5),
+    'page callback' => 'css_get',
+    'access arguments' => array('access content'),
+    'type' => MENU_CALLBACK,
+  );
+
+  return $items;
+}
+
+/**
+ * Returns the CSS for the given field.
+ * Last-Modified header is set to let browsers cache the css.
+ */
+function css_get($entity_type, $entity_id, $field_name, $delta) {
+  $css = '';
+  $entities = entity_load($entity_type, array($entity_id));
+  $date = time();
+
+  // Only proceed if these values exist.
+  if (!empty($entities[$entity_id])) {
+    $entity = $entities[$entity_id];
+    if (!empty($entity->{$field_name})) {
+      $field = $entity->{$field_name};
+      if (!empty($field['und'][$delta])) {
+        $instance = $field['und'][$delta]; // Will this break on multi-lingual entities?
+        if (!empty($instance['value'])) {
+          $css = filter_xss($instance['value']);
+          $date = (!empty($entity->changed)) ? $entity->changed : time();
         }
-        else {
-          // Drupal 6 seems to check for the physical existence of CSS files
-          // before allowing them to be added. We have to include the virtual
-          // CSS file manually since it does not really exist.
-          // To keep the order consistent with Drupal 5 version of CSS module
-          // we had to implement something kind of hacky below. For more details
-          // see http://drupal.org/node/351764
-          if (!empty($node->css_css)) {
-            $attributes = array(
-              'type' => 'text/css',
-              'rel' => 'stylesheet',
-              'media' => 'all',
-              'href' => url('css/get/' . $node->nid),
-            );
-            $link = '<link'. drupal_attributes($attributes) .' />';
-            $css = "\n//--><!]]>\n"."</script>\n".
-           $link . "\n".
-           '<script type="text/javascript">'."\n<!--//--><![CDATA[//><!--\n";
-           drupal_add_js($css, 'inline', 'header', FALSE, FALSE, FALSE);
-          }
-        }
-        break;
-    }
-
-    $prev_op = $op; // used to determine Preview state
-  }
-}
-
-/**
- * Return the css attached to the node.
- * Last-Modified header is set to let browsers cache the css.
- */
-function css_get($nid = 0) {
-  if (is_numeric($nid) && $nid > 0) {
-    $object = db_fetch_object(db_query('SELECT css, changed FROM {css} c, {node} n WHERE n.nid = %d AND n.nid = c.nid', $nid));
-    if ($object) {
-      $date = gmdate('D, d M Y H:i:s', $object->changed) .' GMT';
-      header("Last-Modified: $date");
-      drupal_set_header('Content-Type: text/css; charset=utf-8');
-      print(css_sanitize($object->css));
-    }
-  }
-}
-
-/**
- * Remove harmful code from CSS.
- */
-function css_sanitize($css, $type = 'view') {
-  switch ($type) {
-    case 'view':
-      // Are there any security vulnerabilites from external CSS files?
-      break;
-
-    case 'preview':
-      // Catch potentially malicious code
-      $patterns = array(
-        '~<\s*(/?)\s*(style|script|meta)\s*>~i',
-      );
-      $css = preg_replace($patterns, '<$1FILTERED $2>', $css);
-      break;
-
-    default:
-      $css = '';
-      break;
-  }
-  
-  return $css;
-}
+      }
+    }
+  }
+
+  // Only proceed if $css was found.
+  if (!empty($css)) {
+    drupal_add_http_header('Last-Modified', gmdate('D, d M Y H:i:s', $date) . ' GMT');
+    drupal_add_http_header('Content-Type', 'text/css; charset=utf-8');
+    print($css);
+  }
+
+  // Otherwise give a 404 message.
+  else {
+    drupal_not_found();
+  }
+}
+
+/**
+ * Implements hook_field_info().
+ *
+ * Instance settings:
+ *   - value: the CSS.
+ */
+function css_field_info() {
+  return array(
+    'css' => array(
+      'label' => t('Custom CSS'),
+      'description' => t('This field applies custom CSS.'),
+      'instance_settings' => array('value' => ''),
+      'default_widget' => 'css_widget',
+      'default_formatter' => 'css_default',
+    ),
+  );
+}
+
+/**
+ * Implements hook_field_schema().
+ */
+function css_field_schema($field) {
+  $columns = array();
+
+  if (!empty($field['type'])) {
+    switch ($field['type']) {
+      case 'css':
+        $columns = array(
+          'value' => array(
+            'type' => 'text',
+            'size' => 'big',
+            'not null' => FALSE,
+          ),
+        );
+        break;
+    }
+  }
+
+  return array(
+    'columns' => $columns,
+  );
+}
+
+/**
+ * Implements hook_field_widget_info().
+ */
+function css_field_widget_info() {
+  return array(
+    'css_widget' => array(
+      'label' => t('CSS'),
+      'field types' => array('css'),
+    ),
+  );
+}
+
+/**
+ * Implements hook_field_widget_form().
+ */
+function css_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $base) {
+  $element = $base;
+
+  if (!empty($instance['widget']['type'])) {
+    switch ($instance['widget']['type']) {
+      case 'css_widget':
+        $element = $base + array(
+          'value' => array(
+            '#title' => t('CSS'),
+            '#type' => 'textarea',
+            '#rows' => 10,
+            '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL,
+          ),
+        );
+        break;
+    }
+  }
+
+  return $element;
+}
+
+/**
+ * Implements hook_field_validate().
+ */
+function css_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
+  // TODO: Validate CSS
+}
+
+/**
+ * Implements hook_field_is_empty().
+ */
+function css_field_is_empty($item, $field) {
+  if (empty($item['value'])) {
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+ * Implements hook_field_formatter_info().
+ */
+function css_field_formatter_info() {
+  return array(
+    'css_default' => array(
+      'label' => t('Default'),
+      'field types' => array('css'),
+    ),
+  );
+}
+
+/**
+ * Implements hook_field_formatter_view().
+ */
+function css_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
+  $id_info = entity_extract_ids($entity_type, $entity);
+
+  if (!empty($display['type'])) {
+    switch ($display['type']) {
+      case 'css_default':
+        if (is_array($items) && !empty($items)) {
+          foreach ($items as $delta => $item) {
+            // Only proceed if the necessary fields exist and there is data to
+            // load.
+            if (!empty($id_info[0]) && !empty($field['field_name']) && !empty($item['value'])) {
+              drupal_add_css('css/get/' . $entity_type . '/' . $id_info[0] . '/' . $field['field_name'] . '/' . $delta, array(
+                'type' => 'file',
+                'group' => CSS_THEME,
+                'media' => 'all',
+                'preprocess' => FALSE,
+              ));
+            }
+          }
+        }
+        break;
+    }
+  }
+
+  return array();
+}
